@@ -12,15 +12,18 @@ import SymDenotations.SymDenotation
1212import Names .Name
1313import StdNames .nme
1414import NameOps .*
15- import LazyVals .isVarHandleForLazy
15+ import LazyVals .{ isVarHandleForLazy , isMethodLookupForLazy }
1616
1717import ast .*
1818
1919import scala .collection .mutable
2020
2121import MegaPhase .*
2222
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+ */
2427class MoveStatics extends MiniPhase with SymTransformer {
2528 import ast .tpd .*
2629
@@ -30,7 +33,8 @@ class MoveStatics extends MiniPhase with SymTransformer {
3033
3134 def transformSym (sym : SymDenotation )(using Context ): SymDenotation =
3235 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)) {
3438 sym.owner.asClass.delete(sym.symbol)
3539 sym.owner.companionClass.asClass.enter(sym.symbol)
3640 sym.copySymDenotation(owner = sym.owner.companionClass)
@@ -42,7 +46,11 @@ class MoveStatics extends MiniPhase with SymTransformer {
4246 val (classes, others) = trees.partition(x => x.isInstanceOf [TypeDef ] && x.symbol.isClass)
4347 val pairs = classes.groupBy(_.symbol.name.stripModuleClassSuffix).asInstanceOf [Map [Name , List [TypeDef ]]]
4448
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 = {
4654 val staticFields = newBody.filter(x => x.isInstanceOf [ValDef ] && x.symbol.hasAnnotation(defn.ScalaStaticAnnot )).asInstanceOf [List [ValDef ]]
4755 val newBodyWithStaticConstr =
4856 if (staticFields.nonEmpty) {
@@ -51,8 +59,24 @@ class MoveStatics extends MiniPhase with SymTransformer {
5159 staticCostructor.addAnnotation(Annotation (defn.ScalaStaticAnnot , staticCostructor.span))
5260 staticCostructor.entered
5361
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
5680 }
5781 else newBody
5882
@@ -69,9 +93,12 @@ class MoveStatics extends MiniPhase with SymTransformer {
6993
7094 val staticDefs = mutable.ListBuffer [Tree ]()
7195 val staticTiedDefs = mutable.ListBuffer [Tree ]()
96+ val localStaticDefs = mutable.ListBuffer [ValDef ]()
7297 val remainingDefs = mutable.ListBuffer [Tree ]()
7398
7499 moduleTmpl.body.foreach {
100+ case valDef : ValDef if valDef.symbol.isMethodLookupForLazy && valDef.symbol.isScalaStatic =>
101+ localStaticDefs.addOne(valDef)
75102 case memberDef : MemberDef if memberDef.symbol.isScalaStatic =>
76103 if memberDef.symbol.isVarHandleForLazy then
77104 staticTiedDefs.addOne(memberDef)
@@ -80,7 +107,7 @@ class MoveStatics extends MiniPhase with SymTransformer {
80107 case other => remainingDefs.addOne(other)
81108 }
82109
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
84111 }
85112 }
86113 val newPairs =
@@ -89,7 +116,11 @@ class MoveStatics extends MiniPhase with SymTransformer {
89116 if (classes.tail.isEmpty) {
90117 val classDef = classes.head
91118 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
93124 }
94125 else move(classes.head, classes.tail.head)
95126 Trees .flatten(newPairs.toList.flatten ++ others)
0 commit comments