diff options
author | Martin Odersky <odersky@gmail.com> | 2014-08-24 17:32:27 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-08-24 17:50:52 +0200 |
commit | bdefca99bc8a7ef6c1d895aecad66b81a18fa9e7 (patch) | |
tree | 49e519fb8a9bc45959f00e558e82a9655d0063b7 /src/dotty/tools/dotc/core/Contexts.scala | |
parent | 412fc2ce472acf8b59dba05ee96d3c09a6bb2d41 (diff) | |
download | dotty-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/core/Contexts.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 50 |
1 files changed, 50 insertions, 0 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. */ |