Closed
Description
Even if e2: e1.type, e1.A = e2.A can still fail, in the same way, in Scala and Dotty — as of Dotty 0.16.0-bin-20190606-c46553a-NIGHTLY:
https://gist.github.com/Blaisorblade/3e5a1102c0699f05f1c11333d785a077
See castTestFail*
. We need in fact e2: e1.type & something
, but even then the problem doesn't always appear.
Part of the problem is triggered e2.A
is aliased, because then e.A
can be evaluated too eagerly; it seems Dotty tries to correct for that, but not robustly enough.
object Test {
abstract class ExprBase { s =>
type A
}
abstract class Lit extends ExprBase { s =>
type A = Int
val n: A
}
abstract class LitU extends ExprBase { s =>
type A <: Int
val n: A
}
abstract class LitL extends ExprBase { s =>
type A <: Int
val n: A
}
def castTest1(e1: ExprBase)(e2: e1.type)(x: e1.A): e2.A = x
def castTest2(e1: ExprBase { type A = Int })(e2: e1.type)(x: e1.A): e2.A = x
def castTest3(e1: ExprBase)(e2: ExprBase with e1.type)(x: e2.A): e1.A = x
def castTest4(e1: ExprBase { type A = Int })(e2: ExprBase with e1.type)(x: e2.A): e1.A = x
def castTest5a(e1: ExprBase)(e2: LitU with e1.type)(x: e2.A): e1.A = x
def castTest5b(e1: ExprBase)(e2: LitL with e1.type)(x: e2.A): e1.A = x
//fail:
def castTestFail1(e1: ExprBase)(e2: Lit with e1.type)(x: e2.A): e1.A = x // this is like castTest5a/b, but with Lit instead of LitU/LitL
// the other direction never works:
def castTestFail2a(e1: ExprBase)(e2: Lit with e1.type)(x: e1.A): e2.A = x
def castTestFail2b(e1: ExprBase)(e2: LitL with e1.type)(x: e1.A): e2.A = x
def castTestFail2c(e1: ExprBase)(e2: LitU with e1.type)(x: e1.A): e2.A = x
// the problem isn't about order of intersections.
def castTestFail2bFlip(e1: ExprBase)(e2: e1.type with LitL)(x: e1.A): e2.A = x
def castTestFail2cFlip(e1: ExprBase)(e2: e1.type with LitU)(x: e1.A): e2.A = x
def castTestFail3(e1: ExprBase)(e2: Lit with e1.type)(x: e1.A): e2.A = {
val y: e1.type with e2.type = e2
val z = x: y.A
z
}
}
Errors
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:31:73
[error] 31 | def castTestFail1(e1: ExprBase)(e2: Lit with e1.type)(x: e2.A): e1.A = x // this is like castTest5a/b, but with Lit instead of LitU/LitL
[error] | ^
[error] | Found: e2.A(x)
[error] | Required: e1.A'
[error] |
[error] | where: A is a type in class Lit which is an alias of Int
[error] | A' is a type in class ExprBase
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:33:74
[error] 33 | def castTestFail2a(e1: ExprBase)(e2: Lit with e1.type)(x: e1.A): e2.A = x
[error] | ^
[error] | Found: e1.A(x)
[error] | Required: e2.A'
[error] |
[error] | where: A is a type in class ExprBase
[error] | A' is a type in class Lit which is an alias of Int
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:34:75
[error] 34 | def castTestFail2b(e1: ExprBase)(e2: LitL with e1.type)(x: e1.A): e2.A = x
[error] | ^
[error] | Found: e1.A(x)
[error] | Required: e2.A'
[error] |
[error] | where: A is a type in class ExprBase
[error] | A' is a type in class LitL with bounds <: Int
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:35:75
[error] 35 | def castTestFail2c(e1: ExprBase)(e2: LitU with e1.type)(x: e1.A): e2.A = x
[error] | ^
[error] | Found: e1.A(x)
[error] | Required: e2.A'
[error] |
[error] | where: A is a type in class ExprBase
[error] | A' is a type in class LitU with bounds <: Int
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:38:79
[error] 38 | def castTestFail2bFlip(e1: ExprBase)(e2: e1.type with LitL)(x: e1.A): e2.A = x
[error] | ^
[error] | Found: e1.A(x)
[error] | Required: e2.A'
[error] |
[error] | where: A is a type in class ExprBase
[error] | A' is a type in class LitL with bounds <: Int
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:39:79
[error] 39 | def castTestFail2cFlip(e1: ExprBase)(e2: e1.type with LitU)(x: e1.A): e2.A = x
[error] | ^
[error] | Found: e1.A(x)
[error] | Required: e2.A'
[error] |
[error] | where: A is a type in class ExprBase
[error] | A' is a type in class LitU with bounds <: Int
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/Papers/scala19_gadt_code/src/main/scala/openGADTs.scala:43:12
[error] 43 | val z = x: y.A
[error] | ^
[error] | Found: e1.A(x)
[error] | Required: y.A'
[error] |
[error] | where: A is a type in class ExprBase
[error] | A' is a type in class Lit which is an alias of Int
[error] 7 errors found