aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala101
1 files changed, 101 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
new file mode 100644
index 000000000..9c01aaa9a
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
@@ -0,0 +1,101 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import TreeTransforms._
+import Contexts.Context
+import Flags._
+import SymUtils._
+import Symbols._
+import SymDenotations._
+import Types._
+import Decorators._
+import DenotTransformers._
+import Annotations._
+import StdNames._
+import NameOps._
+import ast.Trees._
+
+/** This phase augments Scala2 traits with implementation classes and with additional members
+ * needed for mixin composition.
+ * These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline.
+ * Specifcally, it adds
+ *
+ * - an implementation class which defines a trait constructor and trait method implementations
+ * - trait setters for vals defined in traits
+ *
+ * Furthermore, it expands the names of all private getters and setters as well as super accessors in the trait and makes
+ * them not-private.
+ */
+class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransformer with FullParameterization { thisTransform =>
+ import ast.tpd._
+
+ override def phaseName: String = "augmentScala2Traits"
+
+ override def rewiredTarget(referenced: Symbol, derived: Symbol)(implicit ctx: Context) = NoSymbol
+
+ override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = {
+ val cls = impl.symbol.owner.asClass
+ for (mixin <- cls.mixins)
+ if (mixin.is(Scala2x))
+ augmentScala2Trait(mixin, cls)
+ impl
+ }
+
+ private def augmentScala2Trait(mixin: ClassSymbol, cls: ClassSymbol)(implicit ctx: Context): Unit = {
+ if (mixin.implClass.is(Scala2x)) () // nothing to do, mixin was already augmented
+ else {
+ //println(i"creating new implclass for $mixin ${mixin.implClass}")
+ val ops = new MixinOps(cls, thisTransform)
+ import ops._
+
+ val implClass = ctx.newCompleteClassSymbol(
+ owner = mixin.owner,
+ name = mixin.name.implClassName,
+ flags = Abstract | Scala2x,
+ parents = defn.ObjectType :: Nil,
+ assocFile = mixin.assocFile).enteredAfter(thisTransform)
+
+ def implMethod(meth: TermSymbol): Symbol = {
+ val mold =
+ if (meth.isConstructor)
+ meth.copySymDenotation(
+ name = nme.TRAIT_CONSTRUCTOR,
+ info = MethodType(Nil, defn.UnitType))
+ else meth.ensureNotPrivate
+ meth.copy(
+ owner = implClass,
+ name = mold.name.asTermName,
+ flags = Method | JavaStatic | mold.flags & ExpandedName,
+ info = fullyParameterizedType(mold.info, mixin))
+ }
+
+ def traitSetter(getter: TermSymbol) =
+ getter.copy(
+ name = getter.ensureNotPrivate.name
+ .expandedName(getter.owner, nme.TRAIT_SETTER_SEPARATOR)
+ .asTermName.setterName,
+ flags = Method | Accessor | ExpandedName,
+ info = MethodType(getter.info.resultType :: Nil, defn.UnitType))
+
+ for (sym <- mixin.info.decls) {
+ if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy) || sym.is(Method, butNot = Deferred))
+ implClass.enter(implMethod(sym.asTerm))
+ if (sym.isGetter)
+ if (sym.is(Lazy)) {
+ if (!sym.hasAnnotation(defn.VolatileAnnot))
+ sym.addAnnotation(Annotation(defn.VolatileAnnot, Nil))
+ }
+ else if (!sym.is(Deferred) && !sym.setter.exists &&
+ !sym.info.resultType.isInstanceOf[ConstantType])
+ traitSetter(sym.asTerm).enteredAfter(thisTransform)
+ if ((sym.is(PrivateAccessor, butNot = ExpandedName) &&
+ (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
+ || sym.is(SuperAccessor)) // scala2 superaccessors are pickled as private, but are compiled as public expanded
+ sym.ensureNotPrivate.installAfter(thisTransform)
+ }
+ ctx.log(i"Scala2x trait decls of $mixin = ${mixin.info.decls.toList.map(_.showDcl)}%\n %")
+ ctx.log(i"Scala2x impl decls of $mixin = ${implClass.info.decls.toList.map(_.showDcl)}%\n %")
+ }
+ }
+}