@@ -16,46 +16,84 @@ import NameOps._
16
16
import Phases ._
17
17
import ast .untpd
18
18
import ast .Trees ._
19
+ import NameKinds .ImplMethName
19
20
import collection .mutable
20
21
21
22
/** Rewrite calls
22
23
*
23
24
* super[M].f(args)
24
25
*
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
26
27
*
27
28
* M$class.f(this, args)
28
29
*
29
30
* 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.
30
36
*/
31
- class LinkScala2ImplClasses extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
37
+ class LinkScala2ImplClasses extends MiniPhase with IdentityDenotTransformer { thisTransform =>
32
38
import ast .tpd ._
33
39
34
40
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
35
47
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)
48
59
}
49
- }
50
60
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
+ }
59
97
}
60
98
61
99
private val Scala2xTrait = allOf(Scala2x , Trait )
0 commit comments