-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GADT patmat doesn't narrow class type parameters #4323
Comments
The issue is not specific to enums: sealed trait Expr[T] {
import Expr._
def join(other: Expr[T]): Expr[T] = (this, other) match {
case (IExpr(i1), IExpr(i2)) => IExpr(i1 + i2)
case (BExpr(b1), BExpr(b2)) => BExpr(b1 & b2)
}
}
object Expr {
case class IExpr(value: Int) extends Expr[Int]
case class BExpr(value: Boolean) extends Expr[Boolean]
} 15 | case (IExpr(i1), IExpr(i2)) => IExpr(i1 + i2)
| ^^^^^^^^^^^^^^
| found: Expr.IExpr
| required: Expr'[T]
|
| where: Expr is a object
| Expr' is a trait
16 | case (BExpr(b1), BExpr(b2)) => BExpr(b1 & b2)
| ^^^^^^^^^^^^^^
| found: Expr.BExpr
| required: Expr'[T]
|
| where: Expr is a object
| Expr' is a trait |
It seems method params aren't refined, but trait params are. Using For instance, works: trait Expr[T]
case class IExpr(value: Int) extends Expr[Int]
case class BExpr(value: Boolean) extends Expr[Boolean]
object Foo {
def foo[T] = {
def join(one: Expr[T], other: Expr[T]): Expr[T] = (one, other) match {
case (IExpr(i1), IExpr(i2)) => IExpr(i1 + i2)
case (BExpr(b1), BExpr(b2)) => BExpr(b1 & b2)
}
}
} Fails: object Foo {
sealed trait Expr[T] {
import Expr._
def join(one: Expr[T], other: Expr[T]): Expr[T] = (one, other) match {
case (IExpr(i1), IExpr(i2)) => IExpr(i1 + i2)
case (BExpr(b1), BExpr(b2)) => BExpr(b1 & b2)
}
}
object Expr {
case class IExpr(value: Int) extends Expr[Int]
case class BExpr(value: Boolean) extends Expr[Boolean]
}
} Writing |
Quotes after type names are used in error messages to distinguish between several types with the same name (we could also use colors or Unicode subscripts if supported by the terminal, but quotes work everywhere) |
@Blaisorblade AFAIU, the first example works because the |
I know, and I'm fine with that for @AleksanderBG Yes, IIUC, that's what I meant with
|
So how do you propose to distinguish between the object Expr and the trait Expr in error messages? |
Why would the compiler's error messages not follow the Scala fact that a value and a type sharing the same name are not ambiguous? (They live in different namespaces.) At the very least it should not have to introduce a difference between the name of a class and its companion object. I propose: | where: value Expr is an object
| type Expr is a trait |
Previously, GADTMap only accepts type bounds, it means we need to force type parameters in order to get their bounds. However forcing type parameters creates a cycle: constr --------> bodyIndex /\ | | | | | | | | | | | type params ----------- We change GADTMap to accept `TermRef` to avoid forcing type params, which breaks the cycle.
I had a problem with this because Anyway, I opened #4355 for this. |
Well, this was actually implemented in #11222, we just forgot about this particular issue. Closing now. |
This is similar to an old issue where class/trait parameters aren't narrowed.
The text was updated successfully, but these errors were encountered: