diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 4946e535cc64..9b5d02854e57 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -600,7 +600,7 @@ object SymDenotations { /** Is this a denotation of a stable term (or an arbitrary type)? */ final def isStable(implicit ctx: Context) = - isType || is(Stable) || !(is(UnstableValue) || info.isInstanceOf[ExprType]) + isType || !is(Erased) && (is(Stable) || !(is(UnstableValue) || info.isInstanceOf[ExprType])) /** Is this a "real" method? A real method is a method which is: * - not an accessor diff --git a/tests/neg/erased-24.scala b/tests/neg/erased-24.scala new file mode 100644 index 000000000000..692ea19794cd --- /dev/null +++ b/tests/neg/erased-24.scala @@ -0,0 +1,25 @@ +// Could become a run test if we had totality checking for erased arguments + +object Test { + + def main(args: Array[String]): Unit = { + println(fun(new Bar)) + } + + def fun(erased foo: Foo): foo.X = { // error + null.asInstanceOf[foo.X] // error + } + + def fun2(erased foo: Foo)(erased bar: foo.B): bar.X = { // error // error + null.asInstanceOf[bar.X] // error + } +} + +class Foo { + type X + type B <: Bar +} + +class Bar extends Foo { + type X = String +} diff --git a/tests/pos/erased-pathdep-1.scala b/tests/neg/erased-pathdep-1.scala similarity index 62% rename from tests/pos/erased-pathdep-1.scala rename to tests/neg/erased-pathdep-1.scala index 159f1fd5aea3..027a08e29582 100644 --- a/tests/pos/erased-pathdep-1.scala +++ b/tests/neg/erased-pathdep-1.scala @@ -1,12 +1,14 @@ +// Could become a neg test if we had totality checking for erased arguments + object Test { fun1(new Bar) fun2(new Bar) fun3(new Bar) - def fun1[F >: Bar <: Foo](erased f: F): f.X = null.asInstanceOf[f.X] - def fun2[F >: Bar <: Foo](erased f: F)(erased bar: f.B): f.B = null.asInstanceOf[f.B] - def fun3[F >: Bar <: Foo](erased f: F)(erased b: f.B): b.X = null.asInstanceOf[b.X] + def fun1[F >: Bar <: Foo](erased f: F): f.X = null.asInstanceOf[f.X] // error // error + def fun2[F >: Bar <: Foo](erased f: F)(erased bar: f.B): f.B = null.asInstanceOf[f.B] // error // error // error + def fun3[F >: Bar <: Foo](erased f: F)(erased b: f.B): b.X = null.asInstanceOf[b.X] // error // error // error } class Foo { diff --git a/tests/pos/erased-pathdep-2.scala b/tests/neg/erased-pathdep-2.scala similarity index 54% rename from tests/pos/erased-pathdep-2.scala rename to tests/neg/erased-pathdep-2.scala index 8fd7cc0dc7fc..29dcf216b32e 100644 --- a/tests/pos/erased-pathdep-2.scala +++ b/tests/neg/erased-pathdep-2.scala @@ -1,10 +1,12 @@ +// Could become a neg test if we had totality checking for erased arguments + object Test { type F >: Bar <: Foo class A(erased val f: F) { - type F1 <: f.X - type F2[Z <: f.X] + type F1 <: f.X // error + type F2[Z <: f.X] // error } } diff --git a/tests/neg/i4060.scala b/tests/neg/i4060.scala new file mode 100644 index 000000000000..2d9321a5ed50 --- /dev/null +++ b/tests/neg/i4060.scala @@ -0,0 +1,22 @@ +class X { type R } +class T(erased val a: X)(val value: a.R) // error + +object App { + def coerce[U, V](u: U): V = { + trait X { type R >: U } + trait Y { type R = V } + + class T[A <: X](erased val a: A)(val value: a.R) // error + + object O { lazy val x : Y & X = ??? } // warning + + val a = new T[Y & X](O.x)(u) + a.value + } + + def main(args: Array[String]): Unit = { + val x: Int = coerce[String, Int]("a") + println(x + 1) + + } +} diff --git a/tests/run/erased-24.check b/tests/run/erased-24.check deleted file mode 100644 index 19765bd501b6..000000000000 --- a/tests/run/erased-24.check +++ /dev/null @@ -1 +0,0 @@ -null diff --git a/tests/run/erased-24.scala b/tests/run/erased-24.scala deleted file mode 100644 index 4faab9d85798..000000000000 --- a/tests/run/erased-24.scala +++ /dev/null @@ -1,23 +0,0 @@ -object Test { - - def main(args: Array[String]): Unit = { - println(fun(new Bar)) - } - - def fun(erased foo: Foo): foo.X = { - null.asInstanceOf[foo.X] - } - - def fun2(erased foo: Foo)(erased bar: foo.B): bar.X = { - null.asInstanceOf[bar.X] - } -} - -class Foo { - type X - type B <: Bar -} - -class Bar extends Foo { - type X = String -}