diff options
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 50 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/MacroTransform.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/TreeTransform.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 4 |
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( |