@@ -21,26 +21,17 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation
21
21
import dotty .tools .dotc .core .SymDenotations .SymDenotation
22
22
import dotty .tools .dotc .core .DenotTransformers .{SymTransformer , IdentityDenotTransformer , DenotTransformer }
23
23
24
- class LazyVals extends MiniPhaseTransform with SymTransformer {
24
+ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
25
25
26
26
import tpd ._
27
27
28
-
29
- def transformSym (d : SymDenotation )(implicit ctx : Context ): SymDenotation = {
30
- if (d is(Flags .Lazy , butNot = Flags .ModuleVal | Flags .Method )) {
31
- // Method flag is set on lazy vals coming from Unpickler. They are already methods and shouldn't be transformed twice
32
- d.copySymDenotation(
33
- initFlags = d.flags | Flags .Method ,
34
- info = ExprType (d.info))
35
- }
36
- else d
37
- }
38
-
39
28
def transformer = new LazyVals
40
29
41
30
val containerFlags = Flags .Synthetic | Flags .Mutable | Flags .Lazy
42
31
val initFlags = Flags .Synthetic | Flags .Method
43
32
33
+ val containerFlagsMask = Flags .Lazy | Flags .Accessor
34
+
44
35
/** this map contains mutable state of transformation: OffsetDefs to be appended to companion object definitions,
45
36
* and number of bits currently used */
46
37
class OffsetInfo (var defs : List [Tree ], var ord : Int )
@@ -52,16 +43,22 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
52
43
* before this phase starts processing same tree */
53
44
// override def ensureAfter: Set[String] = Set("mixin")
54
45
55
- override def transformValDef (tree : ValDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
56
- if (! (tree.mods is Flags .Lazy ) || (tree.mods is Flags . ModuleVal )) tree
46
+ override def transformDefDef (tree : DefDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
47
+ if (! (tree.symbol is Flags .Lazy )) tree
57
48
else {
58
- val isField = tree.symbol.owner.isClass
59
-
60
- if (isField) {
61
- if (tree.symbol.isVolatile) transformFieldValDefVolatile(tree)
62
- else transformFieldValDefNonVolatile(tree)
49
+ if (tree.symbol is Flags .Module ) {
50
+ val field = ctx.newSymbol(tree.symbol.owner, tree.symbol.name ++ StdNames .nme.MODULE_VAR_SUFFIX , containerFlags, tree.symbol.info.resultType, coord = tree.symbol.pos)
51
+ tpd.This (tree.symbol.enclosingClass.asClass).select(defn.Object_synchronized ).appliedTo(
52
+ mkDefNonThreadSafeNonNullable(field, tree.rhs).ensureConforms(tree.tpe.widen.resultType.widen))
53
+ } else {
54
+ val isField = tree.symbol.owner.isClass
55
+
56
+ if (isField) {
57
+ if (tree.symbol.isVolatile) transformFieldValDefVolatile(tree)
58
+ else transformFieldValDefNonVolatile(tree)
59
+ }
60
+ else transformLocalValDef(tree)
63
61
}
64
- else transformLocalValDef(tree)
65
62
}
66
63
}
67
64
@@ -82,12 +79,11 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
82
79
* with a LazyHolder from
83
80
* dotty.runtime(eg dotty.runtime.LazyInt)
84
81
*/
85
- def transformLocalValDef (x : ValDef )(implicit ctx : Context ) = x match {
86
- case ValDef (name, tpt, _) =>
82
+ def transformLocalValDef (x : DefDef )(implicit ctx : Context ) = {
87
83
val valueInitter = x.rhs
88
- val holderName = ctx.freshName(name.toString + StdNames .nme.LAZY_LOCAL ).toTermName
89
- val initName = ctx.freshName(name.toString + StdNames .nme.LAZY_LOCAL_INIT ).toTermName
90
- val tpe = x.tpe.widen
84
+ val holderName = ctx.freshName(x.name + + StdNames .nme.LAZY_LOCAL ).toTermName
85
+ val initName = ctx.freshName(x.name + + StdNames .nme.LAZY_LOCAL_INIT ).toTermName
86
+ val tpe = x.tpe.widen.resultType.widen
91
87
92
88
val holderType =
93
89
if (tpe isRef defn.IntClass ) " LazyInt"
@@ -124,7 +120,12 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
124
120
125
121
126
122
override def transformStats (trees : List [tpd.Tree ])(implicit ctx : Context , info : TransformerInfo ): List [tpd.Tree ] = {
127
- val (holders, stats) = trees.partition { _.symbol.flags == containerFlags}
123
+ val (holders, stats) =
124
+ atGroupEnd { implicit ctx : Context =>
125
+ trees.partition {
126
+ _.symbol.flags == containerFlags
127
+ }
128
+ }
128
129
holders::: stats
129
130
}
130
131
@@ -162,29 +163,28 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
162
163
If (cond, init, exp)
163
164
}
164
165
165
- def transformFieldValDefNonVolatile (x : ValDef )(implicit ctx : Context ) = x match {
166
- case ValDef (name, tpt, _) if (x.mods is Flags .Lazy ) =>
166
+ def transformFieldValDefNonVolatile (x : DefDef )(implicit ctx : Context ) = {
167
167
val claz = x.symbol.owner.asClass
168
- val tpe = x.tpe.widen
168
+ val tpe = x.tpe.widen.resultType.widen
169
169
assert(! (x.mods is Flags .Mutable ))
170
- val containerName = ctx.freshName(name.toString + StdNames .nme.LAZY_LOCAL ).toTermName
171
- val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ Flags . Lazy | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this )
170
+ val containerName = ctx.freshName(x.name + + StdNames .nme.LAZY_LOCAL ).toTermName
171
+ val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this )
172
172
173
173
val containerTree = ValDef (containerSymbol, initValue(tpe))
174
174
if (x.tpe.isNotNull && tpe <:< defn.AnyRefType ) { // can use 'null' value instead of flag
175
175
val slowPath = DefDef (x.symbol.asTerm, mkDefNonThreadSafeNonNullable(containerSymbol, x.rhs))
176
176
Thicket (List (containerTree, slowPath))
177
177
}
178
178
else {
179
- val flagName = ctx.freshName(name.toString + StdNames .nme.BITMAP_PREFIX ).toTermName
179
+ val flagName = ctx.freshName(x.name + + StdNames .nme.BITMAP_PREFIX ).toTermName
180
180
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags, defn.BooleanType )
181
181
val flag = ValDef (flagSymbol, Literal (Constants .Constant (false )))
182
182
val slowPath = DefDef (x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), x.rhs))
183
183
Thicket (List (containerTree, flag, slowPath))
184
184
}
185
185
}
186
186
187
- /** Create non- threadsafe lazy accessor equivalent to such code
187
+ /** Create a threadsafe lazy accessor equivalent to such code
188
188
*
189
189
* def methodSymbol(): Int = {
190
190
* val result: Int = 0
@@ -280,11 +280,10 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
280
280
DefDef (methodSymbol, Block (resultDef :: retryDef :: flagDef :: cycle :: Nil , ref(resultSymbol)))
281
281
}
282
282
283
- def transformFieldValDefVolatile (x : ValDef )(implicit ctx : Context ) = x match {
284
- case ValDef (name, tpt, _) if (x.mods is Flags .Lazy ) =>
283
+ def transformFieldValDefVolatile (x : DefDef )(implicit ctx : Context ) = {
285
284
assert(! (x.mods is Flags .Mutable ))
286
285
287
- val tpe = x.tpe.widen
286
+ val tpe = x.tpe.widen.resultType.widen
288
287
val claz = x.symbol.owner.asClass
289
288
val thiz = This (claz)(ctx.fresh.setOwner(claz))
290
289
val companion = claz.companionModule
@@ -323,8 +322,8 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
323
322
appendOffsetDefs += (companion.name.moduleClassName -> new OffsetInfo (List (offsetTree), ord))
324
323
}
325
324
326
- val containerName = ctx.freshName(name.toString + StdNames .nme.LAZY_LOCAL ).toTermName
327
- val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ Flags . Lazy | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this )
325
+ val containerName = ctx.freshName(x.name + + StdNames .nme.LAZY_LOCAL ).toTermName
326
+ val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this )
328
327
val containerTree = ValDef (containerSymbol, initValue(tpe))
329
328
330
329
val offset = Select (ref(companion), offsetSymbol.name)
0 commit comments