aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala3
-rw-r--r--src/dotty/tools/dotc/transform/AttachOuter.scala65
2 files changed, 67 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 3355ce1f2..ac2e91cec 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -61,7 +61,8 @@ class Compiler {
List(new ElimByName,
new TypeTestsCasts,
new InterceptedMethods,
- new Literalize),
+ new Literalize,
+ new AttachOuter),
List(new Erasure)
)
diff --git a/src/dotty/tools/dotc/transform/AttachOuter.scala b/src/dotty/tools/dotc/transform/AttachOuter.scala
new file mode 100644
index 000000000..9d2b0574d
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/AttachOuter.scala
@@ -0,0 +1,65 @@
+package dotty.tools.dotc
+package transform
+
+import TreeTransforms._
+import core.DenotTransformers._
+import core.Symbols._
+import core.Contexts._
+import core.Types._
+import core.Flags._
+import core.Decorators._
+import core.StdNames.nme
+import ast.Trees._
+import util.Attachment
+
+/** This phase decorates News and parent constructors of non-static inner classes
+ * with an attachment indicating the outer reference as a tree. This is necessary because
+ * outer prefixes are erased, and explicit outer runs only after erasure.
+ */
+class AttachOuter extends MiniPhaseTransform {
+ import ast.tpd._
+
+ val Outer = new Attachment.Key[Tree]
+
+ override def phaseName: String = "attachOuter"
+
+ private def outerPrefix(tpe: Type)(implicit ctx: Context): Type = tpe match {
+ case tpe: TypeRef =>
+ tpe.symbol match {
+ case cls: ClassSymbol =>
+ if (cls.owner.isStaticOwner || cls.is(Interface)) NoPrefix
+ else if (tpe.prefix eq NoPrefix) cls.owner.enclosingClass.thisType
+ else tpe.prefix
+ case _ =>
+ outerPrefix(tpe.underlying)
+ }
+ case tpe: TypeProxy =>
+ outerPrefix(tpe.underlying)
+ }
+
+ override def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val pre = outerPrefix(tree.tpt.tpe)
+ pre match {
+ case pre: SingletonType =>
+ tree.putAttachment(Outer, singleton(pre)) match {
+ case Some(outer) => assert(outer.tpe =:= pre)
+ case none =>
+ }
+ case NoPrefix =>
+ }
+ tree
+ }
+
+ override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ def transformParent(tree: Tree): Tree = tree match {
+ case tree: TypeTree if outerPrefix(tree.tpe) != NoPrefix =>
+ val constr = New(tree.tpe, Nil).withPos(tree.pos)
+ val Select(nu: New, _) = methPart(constr)
+ transformNew(nu)
+ constr
+ case _ =>
+ tree
+ }
+ cpy.Template(tree)(parents = tree.parents mapconserve transformParent)
+ }
+} \ No newline at end of file