Skip to content

Commit 8d080e9

Browse files
committed
Split uninitialized logic from erased definition logic
These two were crammed in PruneErasedDefs even though uninitialized does not share any logic or conceptual similarities.
1 parent 85a03ee commit 8d080e9

File tree

3 files changed

+54
-31
lines changed

3 files changed

+54
-31
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class Compiler {
8282
new ElimByName, // Expand by-name parameter references
8383
new StringInterpolatorOpt) :: // Optimizes raw and s string interpolators by rewriting them to string concatenations
8484
List(new PruneErasedDefs, // Drop erased definitions from scopes and simplify erased expressions
85+
new UninitializedDefs, // Replaces `compiletime.uninitialized` by `_`
8586
new InlinePatterns, // Remove placeholders of inlined patterns
8687
new VCInlineMethods, // Inlines calls to value class methods
8788
new SeqLiterals, // Express vararg arguments as arrays

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

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ import ast.tpd
1919
* The phase also replaces all expressions that appear in an erased context by
2020
* default values. This is necessary so that subsequent checking phases such
2121
* as IsInstanceOfChecker don't give false negatives.
22-
* Finally, the phase replaces `compiletime.uninitialized` on the right hand side
23-
* of a mutable field definition by `_`. This avoids a "is declared erased, but is
24-
* in fact used" error in Erasure and communicates to Constructors that the
25-
* variable does not have an initializer.
2622
*/
2723
class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform =>
2824
import tpd._
@@ -34,39 +30,20 @@ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform =>
3430
override def runsAfterGroupsOf: Set[String] = Set(RefChecks.name, ExplicitOuter.name)
3531

3632
override def transformSym(sym: SymDenotation)(using Context): SymDenotation =
37-
if (sym.isEffectivelyErased && sym.isTerm && !sym.is(Private) && sym.owner.isClass)
38-
sym.copySymDenotation(initFlags = sym.flags | Private)
39-
else sym
33+
if !sym.isEffectivelyErased || !sym.isTerm || sym.is(Private) || !sym.owner.isClass then sym
34+
else sym.copySymDenotation(initFlags = sym.flags | Private)
4035

4136
override def transformApply(tree: Apply)(using Context): Tree =
42-
if (tree.fun.tpe.widen.isErasedMethod)
43-
cpy.Apply(tree)(tree.fun, tree.args.map(trivialErasedTree))
44-
else tree
45-
46-
private def hasUninitializedRHS(tree: ValOrDefDef)(using Context): Boolean =
47-
def recur(rhs: Tree): Boolean = rhs match
48-
case rhs: RefTree =>
49-
rhs.symbol == defn.Compiletime_uninitialized
50-
&& tree.symbol.is(Mutable) && tree.symbol.owner.isClass
51-
case closureDef(ddef) if defn.isContextFunctionType(tree.tpt.tpe.dealias) =>
52-
recur(ddef.rhs)
53-
case _ =>
54-
false
55-
recur(tree.rhs)
37+
if !tree.fun.tpe.widen.isErasedMethod then tree
38+
else cpy.Apply(tree)(tree.fun, tree.args.map(trivialErasedTree))
5639

5740
override def transformValDef(tree: ValDef)(using Context): Tree =
58-
val sym = tree.symbol
59-
if tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty then
60-
cpy.ValDef(tree)(rhs = trivialErasedTree(tree))
61-
else if hasUninitializedRHS(tree) then
62-
cpy.ValDef(tree)(rhs = cpy.Ident(tree.rhs)(nme.WILDCARD).withType(tree.tpt.tpe))
63-
else
64-
tree
41+
if !tree.symbol.isEffectivelyErased || tree.rhs.isEmpty then tree
42+
else cpy.ValDef(tree)(rhs = trivialErasedTree(tree))
6543

6644
override def transformDefDef(tree: DefDef)(using Context): Tree =
67-
if (tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty)
68-
cpy.DefDef(tree)(rhs = trivialErasedTree(tree))
69-
else tree
45+
if !tree.symbol.isEffectivelyErased || tree.rhs.isEmpty then tree
46+
else cpy.DefDef(tree)(rhs = trivialErasedTree(tree))
7047

7148
private def trivialErasedTree(tree: Tree)(using Context): Tree =
7249
tree.tpe.widenTermRefExpr.dealias.normalized match
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import Contexts._
6+
import DenotTransformers.SymTransformer
7+
import Flags._
8+
import SymDenotations._
9+
import Symbols._
10+
import Types._
11+
import typer.RefChecks
12+
import MegaPhase.MiniPhase
13+
import StdNames.nme
14+
import ast.tpd
15+
16+
/** This phase replaces `compiletime.uninitialized` on the right hand side
17+
* of a mutable field definition by `_`. This avoids a "is declared erased, but is
18+
* in fact used" error in Erasure and communicates to Constructors that the
19+
* variable does not have an initializer.
20+
*/
21+
class UninitializedDefs extends MiniPhase:
22+
import tpd._
23+
24+
override def phaseName: String = UninitializedDefs.name
25+
26+
override def transformValDef(tree: ValDef)(using Context): Tree =
27+
if !hasUninitializedRHS(tree) then tree
28+
else cpy.ValDef(tree)(rhs = cpy.Ident(tree.rhs)(nme.WILDCARD).withType(tree.tpt.tpe))
29+
30+
private def hasUninitializedRHS(tree: ValOrDefDef)(using Context): Boolean =
31+
def recur(rhs: Tree): Boolean = rhs match
32+
case rhs: RefTree =>
33+
rhs.symbol == defn.Compiletime_uninitialized
34+
&& tree.symbol.is(Mutable) && tree.symbol.owner.isClass
35+
case closureDef(ddef) if defn.isContextFunctionType(tree.tpt.tpe.dealias) =>
36+
recur(ddef.rhs)
37+
case _ =>
38+
false
39+
recur(tree.rhs)
40+
41+
end UninitializedDefs
42+
43+
object UninitializedDefs:
44+
val name: String = "uninitializedDefs"
45+
end UninitializedDefs

0 commit comments

Comments
 (0)