@@ -16,46 +16,84 @@ import NameOps._
1616import Phases ._
1717import ast .untpd
1818import ast .Trees ._
19+ import NameKinds .ImplMethName
1920import collection .mutable
2021
2122/** Rewrite calls
2223 *
2324 * super[M].f(args)
2425 *
25- * where M is a Scala2 trait implemented by the current class to
26+ * where M is a Scala 2.11 trait implemented by the current class to
2627 *
2728 * M$class.f(this, args)
2829 *
2930 * provided the implementation class M$class defines a corresponding function `f`.
31+ * If M is a Scala 2.12 or newer trait, rewrite to
32+ *
33+ * M.f(this, args)
34+ *
35+ * where f is a static member of M.
3036 */
31- class LinkScala2ImplClasses extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
37+ class LinkScala2ImplClasses extends MiniPhase with IdentityDenotTransformer { thisTransform =>
3238 import ast .tpd ._
3339
3440 override def phaseName : String = " linkScala2ImplClasses"
41+ override def changesMembers = true
42+ val treeTransform = new Transform
43+
44+ override def runsAfterGroupsOf : Set [Class [_ <: Phase ]] = Set (classOf [Mixin ])
45+ // Adds as a side effect static members to traits which can confuse Mixin,
46+ // that's why it is runsAfterGroupOf
3547
36- override def runsAfter : Set [Class [_ <: Phase ]] = Set (classOf [Mixin ])
37-
38- override def transformApply (app : Apply )(implicit ctx : Context , info : TransformerInfo ) = {
39- def currentClass = ctx.owner.enclosingClass.asClass
40- app match {
41- case Apply (sel @ Select (Super (_, _), _), args)
42- if sel.symbol.owner.is(Scala2xTrait ) && currentClass.mixins.contains(sel.symbol.owner) =>
43- val impl = implMethod(sel.symbol)
44- if (impl.exists) Apply (ref(impl), This (currentClass) :: args).withPos(app.pos)
45- else app // could have been an abstract method in a trait linked to from a super constructor
46- case _ =>
47- app
48+ class Transform extends TreeTransform {
49+ def phase = thisTransform
50+
51+ /** Copy definitions from implementation class to trait itself */
52+ private def augmentScala_2_12_Trait (mixin : ClassSymbol )(implicit ctx : Context ): Unit = {
53+ def newImpl (sym : TermSymbol ): Symbol = sym.copy(
54+ owner = mixin,
55+ name = if (sym.isConstructor) sym.name else ImplMethName (sym.name)
56+ )
57+ for (sym <- mixin.implClass.info.decls)
58+ newImpl(sym.asTerm).enteredAfter(thisTransform)
4859 }
49- }
5060
51- private def implMethod (meth : Symbol )(implicit ctx : Context ): Symbol = {
52- val implInfo = meth.owner.implClass.info
53- if (meth.isConstructor)
54- implInfo.decl(nme.TRAIT_CONSTRUCTOR ).symbol
55- else
56- implInfo.decl(meth.name)
57- .suchThat(c => FullParameterization .memberSignature(c.info) == meth.signature)
58- .symbol
61+ override def prepareForTemplate (impl : Template )(implicit ctx : Context ) = {
62+ val cls = impl.symbol.owner.asClass
63+ for (mixin <- cls.mixins)
64+ if (mixin.is(Scala_2_12_Trait , butNot = Scala_2_12_Augmented )) {
65+ augmentScala_2_12_Trait(mixin)
66+ mixin.setFlag(Scala_2_12_Augmented )
67+ }
68+ this
69+ }
70+
71+ override def transformApply (app : Apply )(implicit ctx : Context , info : TransformerInfo ) = {
72+ def currentClass = ctx.owner.enclosingClass.asClass
73+ app match {
74+ case Apply (sel @ Select (Super (_, _), _), args)
75+ if sel.symbol.owner.is(Scala2xTrait ) && currentClass.mixins.contains(sel.symbol.owner) =>
76+ val impl = implMethod(sel.symbol)
77+ if (impl.exists) Apply (ref(impl), This (currentClass) :: args).withPos(app.pos)
78+ else app // could have been an abstract method in a trait linked to from a super constructor
79+ case _ =>
80+ app
81+ }
82+ }
83+
84+ private def implMethod (meth : Symbol )(implicit ctx : Context ): Symbol = {
85+ val (implInfo, implName) =
86+ if (meth.owner.is(Scala_2_12_Trait ))
87+ (meth.owner.info, ImplMethName (meth.name.asTermName))
88+ else
89+ (meth.owner.implClass.info, meth.name)
90+ if (meth.isConstructor)
91+ implInfo.decl(nme.TRAIT_CONSTRUCTOR ).symbol
92+ else
93+ implInfo.decl(implName)
94+ .suchThat(c => FullParameterization .memberSignature(c.info) == meth.signature)
95+ .symbol
96+ }
5997 }
6098
6199 private val Scala2xTrait = allOf(Scala2x , Trait )
0 commit comments