@@ -46,18 +46,35 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
46
46
* before this phase starts processing same tree */
47
47
override def runsAfter = Set (classOf [Mixin ])
48
48
49
- override def transformDefDef (tree : DefDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
50
- if (! (tree.symbol is Flags .Lazy ) || tree.symbol.owner.is(Flags .Trait )) tree
51
- else {
52
- val isField = tree.symbol.owner.isClass
53
-
54
- if (isField) {
55
- if (tree.symbol.isVolatile || tree.symbol.is(Flags .Module )) transformMemberDefVolatile(tree)
56
- else transformMemberDefNonVolatile(tree)
57
- }
58
- else transformLocalDef(tree)
49
+ override def transformDefDef (tree : tpd.DefDef )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree =
50
+ transformLazyVal(tree)
51
+
52
+
53
+ override def transformValDef (tree : tpd.ValDef )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree = {
54
+ transformLazyVal(tree)
55
+ }
56
+
57
+ def transformLazyVal (tree : ValOrDefDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
58
+ val sym = tree.symbol
59
+ if (! (sym is Flags .Lazy ) || sym.owner.is(Flags .Trait ) || (sym.isStatic && sym.is(Flags .Module ))) tree
60
+ else {
61
+
62
+ val isField = sym.owner.isClass
63
+
64
+ if (isField) {
65
+ if (sym.isVolatile ||
66
+ (sym.is(Flags .Module ) && ! sym.is(Flags .Synthetic )))
67
+ // module class is user-defined.
68
+ // Should be threadsafe, to mimic safety guaranteed by global object
69
+ transformMemberDefVolatile(tree)
70
+ else if (sym.is(Flags .Module )) { // synthetic module
71
+ transformSyntheticModule(tree)
72
+ }
73
+ else transformMemberDefNonVolatile(tree)
59
74
}
75
+ else transformLocalDef(tree)
60
76
}
77
+ }
61
78
62
79
63
80
/** Append offset fields to companion objects
@@ -78,11 +95,24 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
78
95
case _ => prefix ::: stats
79
96
}
80
97
98
+ /** Make an eager val that would implement synthetic module.
99
+ * Eager val ensures thread safety and has less code generated.
100
+ *
101
+ */
102
+ def transformSyntheticModule (tree : ValOrDefDef )(implicit ctx : Context ) = {
103
+ val sym = tree.symbol
104
+ val holderSymbol = ctx.newSymbol(sym.owner, sym.asTerm.name ++ nme.LAZY_LOCAL ,
105
+ Flags .Synthetic , sym.info.widen.resultType).enteredAfter(this )
106
+ val field = ValDef (holderSymbol, tree.rhs.changeOwnerAfter(sym, holderSymbol, this ))
107
+ val getter = DefDef (sym.asTerm, ref(holderSymbol))
108
+ Thicket (field, getter)
109
+ }
110
+
81
111
/** Replace a local lazy val inside a method,
82
112
* with a LazyHolder from
83
113
* dotty.runtime(eg dotty.runtime.LazyInt)
84
114
*/
85
- def transformLocalDef (x : DefDef )(implicit ctx : Context ) = {
115
+ def transformLocalDef (x : ValOrDefDef )(implicit ctx : Context ) = {
86
116
val valueInitter = x.rhs
87
117
val holderName = ctx.freshName(x.name ++ StdNames .nme.LAZY_LOCAL ).toTermName
88
118
val initName = ctx.freshName(x.name ++ StdNames .nme.LAZY_LOCAL_INIT ).toTermName
@@ -172,7 +202,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
172
202
If (cond, init, exp)
173
203
}
174
204
175
- def transformMemberDefNonVolatile (x : DefDef )(implicit ctx : Context ) = {
205
+ def transformMemberDefNonVolatile (x : ValOrDefDef )(implicit ctx : Context ) = {
176
206
val claz = x.symbol.owner.asClass
177
207
val tpe = x.tpe.widen.resultType.widen
178
208
assert(! (x.mods is Flags .Mutable ))
@@ -293,7 +323,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
293
323
DefDef (methodSymbol, Block (resultDef :: retryDef :: flagDef :: cycle :: Nil , ref(resultSymbol)))
294
324
}
295
325
296
- def transformMemberDefVolatile (x : DefDef )(implicit ctx : Context ) = {
326
+ def transformMemberDefVolatile (x : ValOrDefDef )(implicit ctx : Context ) = {
297
327
assert(! (x.mods is Flags .Mutable ))
298
328
299
329
val tpe = x.tpe.widen.resultType.widen
0 commit comments