Skip to content

b: a.type but a.A != b.A #6635

Closed
Closed
@Blaisorblade

Description

@Blaisorblade

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions