@@ -12,23 +12,33 @@ import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform
12
12
import dotty .tools .dotc .ast .Trees ._
13
13
import dotty .tools .dotc .ast .{untpd , tpd }
14
14
import dotty .tools .dotc .core .Constants .Constant
15
- import dotty .tools .dotc .core .Types .MethodType
15
+ import dotty .tools .dotc .core .Types .{ ExprType , NoType , MethodType }
16
16
import dotty .tools .dotc .core .Names .Name
17
17
import dotty .runtime .LazyVals
18
18
import SymUtils ._
19
19
import scala .collection .mutable .ListBuffer
20
20
import dotty .tools .dotc .core .Denotations .SingleDenotation
21
21
import dotty .tools .dotc .core .SymDenotations .SymDenotation
22
- import dotty .tools .dotc .core .DenotTransformers .{IdentityDenotTransformer , DenotTransformer }
22
+ import dotty .tools .dotc .core .DenotTransformers .{SymTransformer , IdentityDenotTransformer , DenotTransformer }
23
23
24
- class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer {
24
+ class LazyVals extends MiniPhaseTransform with SymTransformer {
25
25
26
26
import tpd ._
27
27
28
28
29
- def transformer = new LazyValsTransform
29
+ def transformSym (d : SymDenotation )(implicit ctx : Context ): SymDenotation = {
30
+ if (d is(Flags .Lazy , butNot = Flags .ModuleVal )) {
31
+ d.copySymDenotation(
32
+ initFlags = d.flags | Flags .Method ,
33
+ info = ExprType (d.info))
34
+ }
35
+ else d
36
+ }
37
+
38
+ def transformer = new LazyVals
30
39
31
- val containerFlags = Flags .Synthetic | Flags .Mutable
40
+ val containerFlags = Flags .Synthetic | Flags .Mutable | Flags .Lazy
41
+ val initFlags = Flags .Synthetic | Flags .Method
32
42
33
43
/** this map contains mutable state of transformation: OffsetDefs to be appended to companion object definitions,
34
44
* and number of bits currently used */
@@ -72,9 +82,9 @@ class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer
72
82
* dotty.runtime(eg dotty.runtime.LazyInt)
73
83
*/
74
84
def transformLocalValDef (x : ValDef )(implicit ctx : Context ) = x match {
75
- case x@ ValDef (name, tpt, rhs) =>
76
- val valueInitter = rhs
85
+ case x@ ValDef (name, tpt, valueInitter) =>
77
86
val holderName = ctx.freshName(name.toString + StdNames .nme.LAZY_LOCAL ).toTermName
87
+ val initName = ctx.freshName(name.toString + StdNames .nme.LAZY_LOCAL_INIT ).toTermName
78
88
val tpe = x.tpe.widen
79
89
80
90
val holderType =
@@ -88,21 +98,35 @@ class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer
88
98
else if (tpe isRef defn.ShortClass ) " LazyShort"
89
99
else " LazyRef"
90
100
101
+
91
102
val holderImpl = ctx.requiredClass(" dotty.runtime." + holderType)
92
103
93
- val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.symbol.coord)
94
- val holderTree = ValDef (holderSymbol, New (holderImpl.typeRef, List (valueInitter.changeOwner(x.symbol, holderSymbol))))
104
+ val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.pos)
105
+ val initSymbol = ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType (Nil , tpe), coord = x.pos)
106
+ val result = ref(holderSymbol).select(" value" .toTermName)
107
+ val flag = ref(holderSymbol).select(" initialized" .toTermName)
108
+ val initer = valueInitter.changeOwner(x.symbol, initSymbol)
109
+ val initBody =
110
+ ref(holderSymbol).select(defn.Object_synchronized ).appliedToType(tpe).appliedTo(
111
+ mkNonThreadSafeDef(result, flag, initer).ensureConforms(tpe))
112
+ val initTree = DefDef (initSymbol, initBody)
113
+ val holderTree = ValDef (holderSymbol, New (holderImpl.typeRef, List ()))
95
114
val methodBody = {
96
- val prefix = ref(holderSymbol).select(" value" .toTermName)
97
- if (holderType != " LazyRef" ) prefix
98
- else prefix.select(defn.Any_asInstanceOf ).appliedToType(tpe)
115
+ tpd.If (flag, EmptyTree , ref(initSymbol))
116
+ result.ensureConforms(tpe)
99
117
}
100
118
val methodTree = DefDef (x.symbol.asTerm, methodBody)
101
119
ctx.debuglog(s " found a lazy val ${x.show}, \n rewrote with ${holderTree.show}" )
102
- Thicket (holderTree, methodTree)
120
+ Thicket (holderTree, initTree, methodTree)
103
121
}
104
122
105
- /** Create non-threadsafe lazy accessor equivalent to such code
123
+
124
+ override def transformStats (trees : List [tpd.Tree ])(implicit ctx : Context , info : TransformerInfo ): List [tpd.Tree ] = {
125
+ val (holders, stats) = trees.partition { _.symbol.flags == containerFlags}
126
+ holders::: stats
127
+ }
128
+
129
+ /** Create non-threadsafe lazy accessor equivalent to such code
106
130
* def methodSymbol() = {
107
131
* if (flag) target
108
132
* else {
@@ -113,13 +137,11 @@ class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer
113
137
* }
114
138
*/
115
139
116
- def mkNonThreadSafeDef (target : Symbol , flag : Symbol , rhs : Tree )(implicit ctx : Context ) = {
117
- val cond = ref(flag)
118
- val exp = ref(target)
119
- val setFlag = Assign (cond, Literal (Constants .Constant (true )))
120
- val setTarget = Assign (exp, rhs)
121
- val init = Block (List (setFlag, setTarget), exp)
122
- If (cond, exp, init)
140
+ def mkNonThreadSafeDef (target : Tree , flag : Tree , rhs : Tree )(implicit ctx : Context ) = {
141
+ val setFlag = Assign (flag, Literal (Constants .Constant (true )))
142
+ val setTarget = Assign (target, rhs)
143
+ val init = Block (List (setFlag, setTarget), target)
144
+ If (flag, target, init)
123
145
}
124
146
125
147
/** Create non-threadsafe lazy accessor for not-nullable types equivalent to such code
@@ -155,7 +177,7 @@ class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer
155
177
val flagName = ctx.freshName(name.toString + StdNames .nme.BITMAP_PREFIX ).toTermName
156
178
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags, defn.BooleanType )
157
179
val flag = ValDef (flagSymbol, Literal (Constants .Constant (false )))
158
- val slowPath = DefDef (x.symbol.asTerm, mkNonThreadSafeDef(containerSymbol, flagSymbol, rhs))
180
+ val slowPath = DefDef (x.symbol.asTerm, mkNonThreadSafeDef(ref( containerSymbol), ref( flagSymbol) , rhs))
159
181
Thicket (List (containerTree, flag, slowPath))
160
182
}
161
183
0 commit comments