@@ -14,21 +14,21 @@ 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
33
class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer with FullParameterization { thisPhase =>
34
34
import ast .tpd ._
@@ -41,66 +41,34 @@ class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer with F
41
41
42
42
override def transformTemplate (impl : Template )(implicit ctx : Context ): Template = {
43
43
val cls = impl.symbol.owner.asClass
44
- for (mixin <- cls.mixins)
45
- if (mixin.is(Scala2x ))
46
- augmentScala2Trait(mixin, cls)
44
+ for (mixin <- cls.mixins if mixin.is(Scala2x ) && ! mixin.is(Scala2xPartiallyAugmented ))
45
+ augmentScala2Trait(mixin)
47
46
impl
48
47
}
49
48
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 ))
49
+ private def augmentScala2Trait (mixin : ClassSymbol )(implicit ctx : Context ): Unit = {
50
+ def traitSetter (getter : TermSymbol ) =
51
+ getter.copy(
52
+ name = getter.ensureNotPrivate.name
53
+ .expandedName(getter.owner, TraitSetterName )
54
+ .asTermName.setterName,
55
+ flags = Method | Accessor ,
56
+ info = MethodType (getter.info.resultType :: Nil , defn.UnitType ))
85
57
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 % " )
58
+ for (sym <- mixin.info.decls) {
59
+ if (sym.isGetter)
60
+ if (sym.is(Lazy )) {
61
+ if (! sym.hasAnnotation(defn.VolatileAnnot ))
62
+ sym.addAnnotation(Annotation (defn.VolatileAnnot , Nil ))
63
+ }
64
+ else if (! sym.is(Deferred ) && ! sym.setter.exists &&
65
+ ! sym.info.resultType.isInstanceOf [ConstantType ])
66
+ traitSetter(sym.asTerm).enteredAfter(thisPhase)
67
+ if ((sym.is(PrivateAccessor ) && ! sym.name.is(ExpandedName ) &&
68
+ (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
69
+ || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded
70
+ sym.ensureNotPrivate.installAfter(thisPhase)
104
71
}
72
+ mixin.setFlag(Scala2xPartiallyAugmented )
105
73
}
106
74
}
0 commit comments