Skip to content

Commit 800fbbf

Browse files
authored
Merge pull request #4759 from dotty-staging/fix-#4060a
Improve usability of erased values
2 parents 8bfcdaa + 10f96b4 commit 800fbbf

File tree

6 files changed

+16
-24
lines changed

6 files changed

+16
-24
lines changed

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ object CheckRealizable {
5252

5353
def boundsRealizability(tp: Type)(implicit ctx: Context) =
5454
new CheckRealizable().boundsRealizability(tp)
55+
56+
private val LateInitialized = Lazy | Erased,
5557
}
5658

5759
/** Compute realizability status */
@@ -63,10 +65,10 @@ class CheckRealizable(implicit ctx: Context) {
6365
*/
6466
private val checkedFields: mutable.Set[Symbol] = mutable.LinkedHashSet[Symbol]()
6567

66-
/** Is symbol's definitition a lazy val?
68+
/** Is symbol's definitition a lazy or erased val?
6769
* (note we exclude modules here, because their realizability is ensured separately)
6870
*/
69-
private def isLateInitialized(sym: Symbol) = sym.is(Lazy, butNot = Module)
71+
private def isLateInitialized(sym: Symbol) = sym.is(LateInitialized, butNot = Module)
7072

7173
/** The realizability status of given type `tp`*/
7274
def realizability(tp: Type): Realizability = tp.dealias match {
@@ -156,10 +158,10 @@ class CheckRealizable(implicit ctx: Context) {
156158
private def memberRealizability(tp: Type) = {
157159
def checkField(sofar: Realizability, fld: SingleDenotation): Realizability =
158160
sofar andAlso {
159-
if (checkedFields.contains(fld.symbol) || fld.symbol.is(Private | Mutable | Lazy))
161+
if (checkedFields.contains(fld.symbol) || fld.symbol.is(Private | Mutable | Lazy | Erased))
160162
// if field is private it cannot be part of a visible path
161163
// 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
164+
// if field is lazy or erased it does not need to be initialized when the owning object is
163165
// so in all cases the field does not influence realizability of the enclosing object.
164166
Realizable
165167
else {

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

+1-1
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

compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase
9090
}
9191

9292
assert(d.symbol.sourceFile != null &&
93+
ctx.owner.sourceFile != null &&
9394
isSimilar(d.symbol.sourceFile.path, ctx.owner.sourceFile.path),
9495
s"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.owner.sourceFile}")
9596
d.ensureNotPrivate.installAfter(thisPhase)

compiler/src/dotty/tools/dotc/typer/Applications.scala

+3-14
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
799799
}
800800
app match {
801801
case Apply(fun, args) if fun.tpe.widen.isErasedMethod =>
802-
tpd.cpy.Apply(app)(fun = fun, args = args.map(arg => normalizeErasedExpr(arg, "This argument is given to an erased parameter. ")))
802+
tpd.cpy.Apply(app)(fun = fun, args = args.map(arg => defaultValue(arg.tpe)))
803803
case _ => app
804804
}
805805
}
@@ -1567,22 +1567,11 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15671567
harmonizedElems
15681568
}
15691569

1570-
/** Transforms the tree into a its default tree.
1571-
* Performed to shrink the tree that is known to be erased later.
1572-
*/
1573-
protected def normalizeErasedExpr(tree: Tree, msg: String)(implicit ctx: Context): Tree = {
1574-
if (!isPureExpr(tree))
1575-
ctx.warning(msg + "This expression will not be evaluated.", tree.pos)
1576-
defaultValue(tree.tpe)
1577-
}
1578-
15791570
/** Transforms the rhs tree into a its default tree if it is in an `erased` val/def.
15801571
* Performed to shrink the tree that is known to be erased later.
15811572
*/
1582-
protected def normalizeErasedRhs(rhs: Tree, sym: Symbol)(implicit ctx: Context) = {
1583-
if (sym.is(Erased) && rhs.tpe.exists) normalizeErasedExpr(rhs, "Expression is on the RHS of an `erased` " + sym.showKind + ". ")
1584-
else rhs
1585-
}
1573+
protected def normalizeErasedRhs(rhs: Tree, sym: Symbol)(implicit ctx: Context) =
1574+
if (sym.is(Erased) && rhs.tpe.exists) defaultValue(rhs.tpe) else rhs
15861575

15871576
/** If all `types` are numeric value types, and they are not all the same type,
15881577
* pick a common numeric supertype and widen any constant types in `tpes` to it.

tests/neg/erased-24.scala

+3-3
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

+2-2
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)