aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-24 17:32:27 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-24 17:50:52 +0200
commitbdefca99bc8a7ef6c1d895aecad66b81a18fa9e7 (patch)
tree49e519fb8a9bc45959f00e558e82a9655d0063b7 /src/dotty/tools/dotc
parent412fc2ce472acf8b59dba05ee96d3c09a6bb2d41 (diff)
downloaddotty-bdefca99bc8a7ef6c1d895aecad66b81a18fa9e7.tar.gz
dotty-bdefca99bc8a7ef6c1d895aecad66b81a18fa9e7.tar.bz2
dotty-bdefca99bc8a7ef6c1d895aecad66b81a18fa9e7.zip
Fix context for super calls
Super calls need to have special contexts, going beyond super-mode. It's explained in detail in Context#superCallContext. this(...) calls also need special contexts, but this is not enabled yet (some tests fail, need to track down why).
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala50
-rw-r--r--src/dotty/tools/dotc/transform/MacroTransform.scala2
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala12
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala4
6 files changed, 57 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index b662326c5..5f0f6ee6a 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -12,6 +12,7 @@ import Scopes._
import NameOps._
import Uniques._
import SymDenotations._
+import Flags.ParamAccessor
import util.Positions._
import ast.Trees._
import ast.untpd
@@ -259,6 +260,55 @@ object Contexts {
c
}
+ /** The context for a supercall. This context is used for elaborating
+ * the parents of a class and their arguments.
+ * The context is computed from the current class context. It has
+ *
+ * - as owner: The primary constructor of the class
+ * - as outer context: The context enclosing the class context
+ * - as scope: The parameter accessors in the class context
+ * - as mode: inSuperCall
+ *
+ * The reasons for this peculiar choice of attributes are as follows:
+ *
+ * - The constructor must be the owner, because that's where any local methods or closures
+ * should go.
+ * - The context may not see any class members (inherited or defined), and should
+ * instead see definitions defined in the outer context which might be shadowed by
+ * such class members. That's why the outer context must be the outer context of the class.
+ * - At the same time the context should see the parameter accessors of the current class,
+ * that's why they get added to the local scope. An alternative would have been to have the
+ * context see the constructor parameters instead, but then we'd need a final substitution step
+ * from constructor parameters to class paramater accessors.
+ */
+ def superCallContext: Context = {
+ val locals = newScopeWith(owner.decls.filter(_ is ParamAccessor).toList: _*)
+ superOrThisCallContext(owner.primaryConstructor, locals)//.addMode(Mode.InSuperCall)
+ }
+
+ /** The context for the arguments of a this(...) constructor call.
+ * The context is computed from the local auxiliary constructor context.
+ * It has
+ *
+ * - as owner: The auxiliary constructor
+ * - as outer context: The context enclosing the enclosing class context
+ * - as scope: The parameters of the auxiliary constructor.
+ * - as mode: inSuperCall
+ */
+ def thisCallContext: Context = {
+ assert(owner.isClassConstructor)
+ val constrCtx = outersIterator.dropWhile(_.outer.owner == owner).next
+ var classCtx = outersIterator.dropWhile(!_.isClassDefContext).next
+ println(i"locals for this call: ${constrCtx.scope}")
+ classCtx.superOrThisCallContext(owner, constrCtx.scope)
+ }
+
+ /** The super= or this-call context with given owner and locals. */
+ private def superOrThisCallContext(owner: Symbol, locals: Scope): Context = {
+ assert(isClassDefContext)
+ outer.fresh.setOwner(owner).setScope(locals)//.addMode(Mode.InSuperCall)
+ }
+
/** The current source file; will be derived from current
* compilation unit.
*/
diff --git a/src/dotty/tools/dotc/transform/MacroTransform.scala b/src/dotty/tools/dotc/transform/MacroTransform.scala
index 734380661..47ffaafb3 100644
--- a/src/dotty/tools/dotc/transform/MacroTransform.scala
+++ b/src/dotty/tools/dotc/transform/MacroTransform.scala
@@ -62,7 +62,7 @@ abstract class MacroTransform extends Phase {
case Template(constr, parents, self, body) =>
cpy.Template(tree)(
transformSub(constr),
- transform(parents),
+ transform(parents)(ctx.superCallContext),
transformSelf(self),
transformStats(body, tree.symbol))
case _ =>
diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala
index c734f1ced..98447cc40 100644
--- a/src/dotty/tools/dotc/transform/TreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/TreeTransform.scala
@@ -1145,7 +1145,7 @@ object TreeTransforms {
if (mutatedInfo eq null) tree
else {
val constr = transformSub(tree.constr, mutatedInfo, cur)
- val parents = transformTrees(tree.parents, mutatedInfo, cur)
+ val parents = transformTrees(tree.parents, mutatedInfo, cur)(ctx.superCallContext)
val self = transformSub(tree.self, mutatedInfo, cur)
val body = transformStats(tree.body, tree.symbol, mutatedInfo, cur)
goTemplate(cpy.Template(tree)(constr, parents, self, body), mutatedInfo.nx.nxTransTemplate(cur))
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 20a5a1204..782faf0d4 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -462,7 +462,7 @@ class Namer { typer: Typer =>
}
def checkedParentType(parent: untpd.Tree): Type = {
- val ptype = parentType(parent)(ctx.fresh addMode Mode.InSuperCall)
+ val ptype = parentType(parent)(ctx.superCallContext)
if (cls.isRefinementClass) ptype
else checkClassTypeWithStablePrefix(ptype, parent.pos, traitReq = parent ne parents.head)
}
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 50b0fe8c1..7bb6fccc3 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -12,20 +12,12 @@ import config.Printers._
trait TypeAssigner {
import tpd._
- /** The enclosing class, except if we are in a super call, in which case
- * it is the next outer one.
- */
- def effectiveEnclosingClass(implicit ctx: Context) = {
- val enclClass = ctx.owner.enclosingClass
- if ((ctx.mode is Mode.InSuperCall) && enclClass.exists) enclClass.owner.enclosingClass
- else enclClass
- }
-
/** The qualifying class of a this or super with prefix `qual` (which might be empty).
* @param packageOk The qualifier may refer to a package.
*/
def qualifyingClass(tree: untpd.Tree, qual: Name, packageOK: Boolean)(implicit ctx: Context): Symbol = {
- effectiveEnclosingClass.ownersIterator.find(o => qual.isEmpty || o.isClass && o.name == qual) match {
+ def qualifies(sym: Symbol) = sym.isClass && (qual.isEmpty || sym.name == qual)
+ ctx.outersIterator.map(_.owner).find(qualifies) match {
case Some(c) if packageOK || !(c is Package) =>
c
case _ =>
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 1cfd03e4c..67c9e15af 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -818,7 +818,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context) = track("typedClassDef") {
- val superCtx = ctx.fresh addMode Mode.InSuperCall
+ val TypeDef(mods, name, impl @ Template(constr, parents, self, body)) = cdef
+ val superCtx = ctx.superCallContext
def typedParent(tree: untpd.Tree): Tree =
if (tree.isType) typedType(tree)(superCtx)
else {
@@ -838,7 +839,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
else parents
}
- val TypeDef(mods, name, impl @ Template(constr, parents, self, body)) = cdef
val mods1 = addTypedModifiersAnnotations(mods, cls)
val constr1 = typed(constr).asInstanceOf[DefDef]
val parents1 = ensureConstrCall(ensureFirstIsClass(