@@ -14,93 +14,59 @@ import Annotations._
14
14
import StdNames ._
15
15
import NameOps ._
16
16
import NameKinds .{ExpandedName , TraitSetterName }
17
+ import ast .Trees ._
17
18
18
19
object AugmentScala2Traits {
19
20
val name : String = " augmentScala2Traits"
20
21
}
21
22
22
- /** This phase augments Scala2 traits with implementation classes and with additional members
23
- * needed for mixin composition.
24
- * These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline.
25
- * Specifically, it adds
23
+ /** This phase augments Scala2 traits with additional members needed for mixin composition.
26
24
*
27
- * - an implementation class which defines a trait constructor and trait method implementations
28
- * - trait setters for vals defined in traits
25
+ * These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline.
29
26
*
30
- * Furthermore, it expands the names of all private getters and setters as well as super accessors in the trait and makes
31
- * them not-private.
27
+ * Specifically, we:
28
+ * - Mark all lazy val fields as @volatile to get the proper Scala 2 semantics.
29
+ * - Add trait setters for vals defined in traits.
30
+ * - Expand the names of all private getters and setters as well as super accessors in the trait and make
31
+ * not-private.
32
32
*/
33
- class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer with FullParameterization { thisPhase =>
33
+ class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer { thisPhase =>
34
34
import ast .tpd ._
35
35
36
36
override def changesMembers : Boolean = true
37
37
38
38
override def phaseName : String = AugmentScala2Traits .name
39
39
40
- override def rewiredTarget (referenced : Symbol , derived : Symbol )(implicit ctx : Context ): Symbol = NoSymbol
41
-
42
40
override def transformTemplate (impl : Template )(implicit ctx : Context ): Template = {
43
41
val cls = impl.symbol.owner.asClass
44
- for (mixin <- cls.mixins)
45
- if (mixin.is(Scala2x ))
46
- augmentScala2Trait(mixin, cls)
42
+ for (mixin <- cls.mixins if mixin.is(Scala2x ) && ! mixin.is(Scala2xPartiallyAugmented ))
43
+ augmentScala2Trait(mixin)
47
44
impl
48
45
}
49
46
50
- private def augmentScala2Trait (mixin : ClassSymbol , cls : ClassSymbol )(implicit ctx : Context ): Unit = {
51
- if (mixin.implClass.is(Scala2x )) () // nothing to do, mixin was already augmented
52
- else {
53
- // println(i"creating new implclass for $mixin ${mixin.implClass}")
54
- val ops = new MixinOps (cls, thisPhase)
55
- import ops ._
56
-
57
- val implClass = ctx.newCompleteClassSymbol(
58
- owner = mixin.owner,
59
- name = mixin.name.implClassName,
60
- flags = Abstract | Scala2x | ImplClass ,
61
- parents = defn.ObjectType :: Nil ,
62
- assocFile = mixin.assocFile).enteredAfter(thisPhase)
63
-
64
- def implMethod (meth : TermSymbol ): Symbol = {
65
- val mold =
66
- if (meth.isConstructor)
67
- meth.copySymDenotation(
68
- name = nme.TRAIT_CONSTRUCTOR ,
69
- info = MethodType (Nil , defn.UnitType ))
70
- else meth.ensureNotPrivate
71
- meth.copy(
72
- owner = implClass,
73
- name = mold.name.asTermName,
74
- flags = Method | JavaStatic ,
75
- info = fullyParameterizedType(mold.info, mixin))
76
- }
77
-
78
- def traitSetter (getter : TermSymbol ) =
79
- getter.copy(
80
- name = getter.ensureNotPrivate.name
81
- .expandedName(getter.owner, TraitSetterName )
82
- .asTermName.setterName,
83
- flags = Method | Accessor ,
84
- info = MethodType (getter.info.resultType :: Nil , defn.UnitType ))
47
+ private def augmentScala2Trait (mixin : ClassSymbol )(implicit ctx : Context ): Unit = {
48
+ def traitSetter (getter : TermSymbol ) =
49
+ getter.copy(
50
+ name = getter.ensureNotPrivate.name
51
+ .expandedName(getter.owner, TraitSetterName )
52
+ .asTermName.setterName,
53
+ flags = Method | Accessor ,
54
+ info = MethodType (getter.info.resultType :: Nil , defn.UnitType ))
85
55
86
- for (sym <- mixin.info.decls) {
87
- if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy ) || sym.is(Method , butNot = Deferred ))
88
- implClass.enter(implMethod(sym.asTerm))
89
- if (sym.isGetter)
90
- if (sym.is(Lazy )) {
91
- if (! sym.hasAnnotation(defn.VolatileAnnot ))
92
- sym.addAnnotation(Annotation (defn.VolatileAnnot , Nil ))
93
- }
94
- else if (! sym.is(Deferred ) && ! sym.setter.exists &&
95
- ! sym.info.resultType.isInstanceOf [ConstantType ])
96
- traitSetter(sym.asTerm).enteredAfter(thisPhase)
97
- if ((sym.is(PrivateAccessor ) && ! sym.name.is(ExpandedName ) &&
98
- (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
99
- || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded
100
- sym.ensureNotPrivate.installAfter(thisPhase)
101
- }
102
- ctx.log(i " Scala2x trait decls of $mixin = ${mixin.info.decls.toList.map(_.showDcl)}% \n % " )
103
- ctx.log(i " Scala2x impl decls of $mixin = ${implClass.info.decls.toList.map(_.showDcl)}% \n % " )
56
+ for (sym <- mixin.info.decls) {
57
+ if (sym.isGetter)
58
+ if (sym.is(Lazy )) {
59
+ if (! sym.hasAnnotation(defn.VolatileAnnot ))
60
+ sym.addAnnotation(Annotation (defn.VolatileAnnot , Nil ))
61
+ }
62
+ else if (! sym.is(Deferred ) && ! sym.setter.exists &&
63
+ ! sym.info.resultType.isInstanceOf [ConstantType ])
64
+ traitSetter(sym.asTerm).enteredAfter(thisPhase)
65
+ if ((sym.is(PrivateAccessor ) && ! sym.name.is(ExpandedName ) &&
66
+ (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
67
+ || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded
68
+ sym.ensureNotPrivate.installAfter(thisPhase)
104
69
}
70
+ mixin.setFlag(Scala2xPartiallyAugmented )
105
71
}
106
72
}
0 commit comments