aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-09-17 12:01:29 +0200
committerMartin Odersky <odersky@gmail.com>2015-09-17 12:01:44 +0200
commit50e3a7d92f4b7cc4cd922eb92c7ed8bf793b159c (patch)
treeb9e730f476167186316f9a684000cec04cd841d0
parent7ee013745699029830a822d0b9e1e8862eaa0b8c (diff)
downloaddotty-50e3a7d92f4b7cc4cd922eb92c7ed8bf793b159c.tar.gz
dotty-50e3a7d92f4b7cc4cd922eb92c7ed8bf793b159c.tar.bz2
dotty-50e3a7d92f4b7cc4cd922eb92c7ed8bf793b159c.zip
New phase: ExplicitSelf
Makes self types explicit, if this is needed to identify a member in a select. Fixes #789.
-rw-r--r--src/dotty/tools/dotc/Compiler.scala1
-rw-r--r--src/dotty/tools/dotc/core/Types.scala5
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitSelf.scala37
-rw-r--r--tests/run/i789.check1
-rw-r--r--tests/run/i789.scala20
5 files changed, 63 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index c537d8885..a36743b59 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -52,6 +52,7 @@ class Compiler {
new ClassOf),
List(new PatternMatcher,
new ExplicitOuter,
+ new ExplicitSelf,
new Splitter),
List(new VCInlineMethods,
new SeqLiterals,
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index d04da30c0..358720836 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2530,7 +2530,7 @@ object Types {
def selfType(implicit ctx: Context): Type = {
if (selfTypeCache == null)
selfTypeCache = {
- def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams)
+ def fullRef = fullyAppliedRef
val given = givenSelfType
val raw =
if (!given.exists) fullRef
@@ -2561,6 +2561,9 @@ object Types {
base
}
+ /** The class type with all type parameters */
+ def fullyAppliedRef(implicit ctx: Context): Type = fullyAppliedRef(cls.typeRef, cls.typeParams)
+
def rebase(tp: Type)(implicit ctx: Context): Type =
if ((prefix eq cls.owner.thisType) || !cls.owner.isClass || ctx.erasedTypes) tp
else tp.substThis(cls.owner.asClass, prefix)
diff --git a/src/dotty/tools/dotc/transform/ExplicitSelf.scala b/src/dotty/tools/dotc/transform/ExplicitSelf.scala
new file mode 100644
index 000000000..c6a218157
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/ExplicitSelf.scala
@@ -0,0 +1,37 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import Contexts.Context
+import Types._
+import TreeTransforms._
+import Decorators._
+import ast.Trees._
+import Flags._
+
+/** Transform references of the form
+ *
+ * C.this.m
+ *
+ * where `C` is a class with explicit self type and `C` is not a
+ * subclass of the owner of `m` to
+ *
+ * C.this.asInstanceOf[S].m
+ *
+ * where `S` is the self type of `C`.
+ */
+class ExplicitSelf extends MiniPhaseTransform { thisTransform =>
+ import ast.tpd._
+
+ override def phaseName = "explicitSelf"
+
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = tree match {
+ case Select(thiz: This, name) if name.isTermName =>
+ val cls = thiz.symbol.asClass
+ val cinfo = cls.classInfo
+ if (cinfo.givenSelfType.exists && !cls.derivesFrom(tree.symbol.owner))
+ cpy.Select(tree)(thiz.asInstance(cinfo.selfType), name)
+ else tree
+ case _ => tree
+ }
+}
diff --git a/tests/run/i789.check b/tests/run/i789.check
new file mode 100644
index 000000000..d41f69423
--- /dev/null
+++ b/tests/run/i789.check
@@ -0,0 +1 @@
+atPhase: 2
diff --git a/tests/run/i789.scala b/tests/run/i789.scala
new file mode 100644
index 000000000..99b081f0a
--- /dev/null
+++ b/tests/run/i789.scala
@@ -0,0 +1,20 @@
+ trait Periods { self: Context =>
+
+ def atPhase(id: Int): Unit = println(s"atPhase: $id")
+
+ }
+
+ class Phase(val id: Int)
+
+ trait Phases { self: Context =>
+ def atPhase(phase: Phase): Unit = self.atPhase(phase.id)
+ }
+
+ trait Context extends Phases with Periods
+
+ object Test extends Context {
+
+ def main(args: Array[String]) = atPhase(new Phase(2))
+
+ }
+