@@ -12,15 +12,18 @@ import SymDenotations.SymDenotation
12
12
import Names .Name
13
13
import StdNames .nme
14
14
import NameOps .*
15
- import LazyVals .isVarHandleForLazy
15
+ import LazyVals .{ isVarHandleForLazy , isMethodLookupForLazy }
16
16
17
17
import ast .*
18
18
19
19
import scala .collection .mutable
20
20
21
21
import MegaPhase .*
22
22
23
- /** Move static methods from companion to the class itself */
23
+ /** Move static methods from companion to the class itself. Also create the static constructor.
24
+ * VarHandles generated by the compiler (more in LazyVals.scala) are left in the original class.
25
+ * MethodSymbols.lookup() generated by the compiler is extracted to be a local static constructor value.
26
+ */
24
27
class MoveStatics extends MiniPhase with SymTransformer {
25
28
import ast .tpd .*
26
29
@@ -30,7 +33,8 @@ class MoveStatics extends MiniPhase with SymTransformer {
30
33
31
34
def transformSym (sym : SymDenotation )(using Context ): SymDenotation =
32
35
if (sym.hasAnnotation(defn.ScalaStaticAnnot ) && sym.owner.is(Flags .Module ) && sym.owner.companionClass.exists &&
33
- (sym.is(Flags .Method ) || ! (sym.isMutableVarOrAccessor && sym.owner.companionClass.is(Flags .Trait )) && ! sym.symbol.isVarHandleForLazy)) {
36
+ (sym.is(Flags .Method ) || ! (sym.isMutableVarOrAccessor && sym.owner.companionClass.is(Flags .Trait )) &&
37
+ ! sym.symbol.isVarHandleForLazy && ! sym.symbol.isMethodLookupForLazy)) {
34
38
sym.owner.asClass.delete(sym.symbol)
35
39
sym.owner.companionClass.asClass.enter(sym.symbol)
36
40
sym.copySymDenotation(owner = sym.owner.companionClass)
@@ -42,7 +46,11 @@ class MoveStatics extends MiniPhase with SymTransformer {
42
46
val (classes, others) = trees.partition(x => x.isInstanceOf [TypeDef ] && x.symbol.isClass)
43
47
val pairs = classes.groupBy(_.symbol.name.stripModuleClassSuffix).asInstanceOf [Map [Name , List [TypeDef ]]]
44
48
45
- def rebuild (orig : TypeDef , newBody : List [Tree ]): Tree = {
49
+ /** Rebuilds a template with static ValDefs from `newBody`` initialized in a static constructor.
50
+ * `localStaticDefs`, used for initialisation of other static values,
51
+ * are moved entirely into the static constructor.
52
+ */
53
+ def rebuild (orig : TypeDef , newBody : List [Tree ], localStaticDefs : List [ValDef ]): Tree = {
46
54
val staticFields = newBody.filter(x => x.isInstanceOf [ValDef ] && x.symbol.hasAnnotation(defn.ScalaStaticAnnot )).asInstanceOf [List [ValDef ]]
47
55
val newBodyWithStaticConstr =
48
56
if (staticFields.nonEmpty) {
@@ -51,8 +59,24 @@ class MoveStatics extends MiniPhase with SymTransformer {
51
59
staticCostructor.addAnnotation(Annotation (defn.ScalaStaticAnnot , staticCostructor.span))
52
60
staticCostructor.entered
53
61
54
- val staticAssigns = staticFields.map(x => Assign (ref(x.symbol), x.rhs.changeOwner(x.symbol, staticCostructor)))
55
- tpd.DefDef (staticCostructor, Block (staticAssigns, tpd.unitLiteral)) :: newBody
62
+ val symbolRemap = localStaticDefs.map { x =>
63
+ x.symbol.owner.asClass.delete(x.symbol)
64
+ x.changeOwner(x.symbol.owner, staticCostructor)
65
+ (x.symbol, x.symbol.copy(owner = staticCostructor))
66
+ }.toMap
67
+
68
+ val localValDefs = localStaticDefs.map ( vDef =>
69
+ val newSymbol = symbolRemap(vDef.symbol)
70
+ ValDef (newSymbol.asTerm, vDef.rhs.changeOwner(vDef.symbol, newSymbol))
71
+ )
72
+
73
+ val localValDefMapper = new TreeMap :
74
+ override def transform (tree : Tree )(using Context ): Tree = tree match
75
+ case ident @ Ident (tp) if symbolRemap.contains(ident.symbol) => ref(symbolRemap(ident.symbol))
76
+ case _ => super .transform(tree)
77
+
78
+ val staticAssigns = staticFields.map(x => Assign (ref(x.symbol), localValDefMapper.transform(x.rhs).changeOwner(x.symbol, staticCostructor)))
79
+ tpd.DefDef (staticCostructor, Block (localValDefs ++ staticAssigns, tpd.unitLiteral)) :: newBody
56
80
}
57
81
else newBody
58
82
@@ -69,9 +93,12 @@ class MoveStatics extends MiniPhase with SymTransformer {
69
93
70
94
val staticDefs = mutable.ListBuffer [Tree ]()
71
95
val staticTiedDefs = mutable.ListBuffer [Tree ]()
96
+ val localStaticDefs = mutable.ListBuffer [ValDef ]()
72
97
val remainingDefs = mutable.ListBuffer [Tree ]()
73
98
74
99
moduleTmpl.body.foreach {
100
+ case valDef : ValDef if valDef.symbol.isMethodLookupForLazy && valDef.symbol.isScalaStatic =>
101
+ localStaticDefs.addOne(valDef)
75
102
case memberDef : MemberDef if memberDef.symbol.isScalaStatic =>
76
103
if memberDef.symbol.isVarHandleForLazy then
77
104
staticTiedDefs.addOne(memberDef)
@@ -80,7 +107,7 @@ class MoveStatics extends MiniPhase with SymTransformer {
80
107
case other => remainingDefs.addOne(other)
81
108
}
82
109
83
- rebuild(companion, companionTmpl.body ++ staticDefs) :: rebuild(module, staticTiedDefs.toList ++ remainingDefs.toList) :: Nil
110
+ rebuild(companion, companionTmpl.body ++ staticDefs, Nil ) :: rebuild(module, staticTiedDefs.toList ++ remainingDefs.toList, localStaticDefs .toList) :: Nil
84
111
}
85
112
}
86
113
val newPairs =
@@ -89,7 +116,11 @@ class MoveStatics extends MiniPhase with SymTransformer {
89
116
if (classes.tail.isEmpty) {
90
117
val classDef = classes.head
91
118
val tmpl = classDef.rhs.asInstanceOf [Template ]
92
- rebuild(classDef, tmpl.body) :: Nil
119
+ val (localStaticDefs, remainingDefs) = tmpl.body.partition {
120
+ case valDef : ValDef => valDef.symbol.isMethodLookupForLazy && valDef.symbol.isScalaStatic
121
+ case _ => false
122
+ }
123
+ rebuild(classDef, remainingDefs, localStaticDefs.asInstanceOf [List [ValDef ]]) :: Nil
93
124
}
94
125
else move(classes.head, classes.tail.head)
95
126
Trees .flatten(newPairs.toList.flatten ++ others)
0 commit comments