Skip to content

Commit 61b2da0

Browse files
committed
Fix #2468: Replace wildcards in a mini-phase
1 parent e51d44a commit 61b2da0

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ class Compiler {
9595
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
9696
new ElimStaticThis, // Replace `this` references to static objects by global identifiers
9797
new Flatten, // Lift all inner classes to package scope
98-
new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group
98+
new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group
99+
new TransformWildcards), // Replace wildcards with default values
99100
List(new MoveStatics, // Move static methods to companion classes
100101
new ExpandPrivate, // Widen private definitions accessed from nested classes
101102
new SelectStatic, // get rid of selects that would be compiled into GetStatic
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import TreeTransforms._
5+
import core.DenotTransformers._
6+
import core.Contexts._
7+
import ast.Trees._
8+
import ast.tpd
9+
import core.Constants.Constant
10+
import core.StdNames._
11+
import core.Symbols._
12+
13+
14+
class TransformWildcards extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
15+
import tpd._
16+
17+
override def phaseName = "transformWildcards"
18+
19+
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
20+
tree match {
21+
case ValDef(_, _, Ident(name)) => assert(name ne nme.WILDCARD)
22+
case _ =>
23+
}
24+
}
25+
26+
override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
27+
tree.rhs match {
28+
case Ident(nme.WILDCARD) =>
29+
val literal = defaultValueLiteral(tree)
30+
cpy.ValDef(tree)(rhs = literal)
31+
case _ => tree
32+
}
33+
}
34+
35+
def defaultValueLiteral(tree: ValDef)(implicit ctx: Context) = {
36+
val t = tree.rhs.tpe.widenDealias.classSymbol
37+
38+
if (t eq defn.DoubleClass) Literal(Constant(0.0d))
39+
else if (t eq defn.IntClass) Literal(Constant(0))
40+
else if (t eq defn.CharClass) Literal(Constant('\u0000'))
41+
else if (t eq defn.ByteClass) Literal(Constant(0: Byte))
42+
else if (t eq defn.LongClass) Literal(Constant(0L))
43+
else if (t eq defn.FloatClass) Literal(Constant(0f))
44+
else if (t eq defn.UnitClass) Literal(Constant(()))
45+
else if (t eq defn.BooleanClass) Literal(Constant(false))
46+
else Literal(Constant(null))
47+
}
48+
}

tests/pos/i2468.scala

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
object Test {
3+
4+
class A {
5+
private[this] var x: String = _
6+
}
7+
8+
class B {
9+
private[this] var x: String = _
10+
x = "foo"
11+
}
12+
13+
class C {
14+
private[this] var x1: Int = _
15+
private[this] var x2: Unit = _
16+
private[this] var x3: Char = _
17+
private[this] var x4: Boolean = _
18+
private[this] var x5: Float = _
19+
private[this] var x6: Double = _
20+
private[this] var x7: Char = _
21+
private[this] var x8: Byte = _
22+
private[this] var x9: AnyVal = _
23+
private[this] var x10: D = _
24+
}
25+
26+
class D(x: Int) extends AnyVal
27+
}

0 commit comments

Comments
 (0)