Skip to content

Commit 6a12079

Browse files
committed
Erased values are stable but not realizable
In that sense they behave exactly like lazy vals. Making them unstable threw out most use cases. We typically set up an erased value because it contains interesting types. But to get at the types the values have to be stable in the first place!
1 parent 2267712 commit 6a12079

File tree

4 files changed

+10
-10
lines changed

4 files changed

+10
-10
lines changed

compiler/src/dotty/tools/dotc/core/CheckRealizable.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ class CheckRealizable(implicit ctx: Context) {
6363
*/
6464
private val checkedFields: mutable.Set[Symbol] = mutable.LinkedHashSet[Symbol]()
6565

66-
/** Is symbol's definitition a lazy val?
66+
/** Is symbol's definitition a lazy or erased val?
6767
* (note we exclude modules here, because their realizability is ensured separately)
6868
*/
69-
private def isLateInitialized(sym: Symbol) = sym.is(Lazy, butNot = Module)
69+
private def isLateInitialized(sym: Symbol) = sym.is(Lazy | Erased, butNot = Module)
7070

7171
/** The realizability status of given type `tp`*/
7272
def realizability(tp: Type): Realizability = tp.dealias match {
@@ -156,10 +156,10 @@ class CheckRealizable(implicit ctx: Context) {
156156
private def memberRealizability(tp: Type) = {
157157
def checkField(sofar: Realizability, fld: SingleDenotation): Realizability =
158158
sofar andAlso {
159-
if (checkedFields.contains(fld.symbol) || fld.symbol.is(Private | Mutable | Lazy))
159+
if (checkedFields.contains(fld.symbol) || fld.symbol.is(Private | Mutable | Lazy | Erased))
160160
// if field is private it cannot be part of a visible path
161161
// if field is mutable it cannot be part of a path
162-
// if field is lazy it does not need to be initialized when the owning object is
162+
// if field is lazy or erased it does not need to be initialized when the owning object is
163163
// so in all cases the field does not influence realizability of the enclosing object.
164164
Realizable
165165
else {

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ object SymDenotations {
597597

598598
/** Is this a denotation of a stable term (or an arbitrary type)? */
599599
final def isStable(implicit ctx: Context) =
600-
isType || !is(Erased) && (is(Stable) || !(is(UnstableValue) || info.isInstanceOf[ExprType]))
600+
isType || is(Stable) || !(is(UnstableValue) || info.isInstanceOf[ExprType])
601601

602602
/** Is this a "real" method? A real method is a method which is:
603603
* - not an accessor

tests/neg/erased-24.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ object Test {
66
println(fun(new Bar))
77
}
88

9-
def fun(erased foo: Foo): foo.X = { // error
10-
null.asInstanceOf[foo.X] // error
9+
def fun(erased foo: Foo): foo.X = { // ok
10+
null.asInstanceOf[foo.X] // ok
1111
}
1212

13-
def fun2(erased foo: Foo)(erased bar: foo.B): bar.X = { // error // error
13+
def fun2(erased foo: Foo)(erased bar: foo.B): bar.X = { // error
1414
null.asInstanceOf[bar.X] // error
1515
}
1616
}

tests/neg/i4060.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class X { type R }
2-
class T(erased val a: X)(val value: a.R) // error
2+
class T(erased val a: X)(val value: a.R)
33

44
object App {
55
def coerce[U, V](u: U): V = {
@@ -8,7 +8,7 @@ object App {
88

99
class T[A <: X](erased val a: A)(val value: a.R) // error
1010

11-
object O { lazy val x : Y & X = ??? } // warning
11+
object O { lazy val x : Y & X = ??? }
1212

1313
val a = new T[Y & X](O.x)(u)
1414
a.value

0 commit comments

Comments
 (0)