diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2011-01-26 07:34:03 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2011-01-26 07:34:03 +0000 |
commit | 78007ac467c9d6e88ae183a9126772829072704c (patch) | |
tree | 25a9e8060fc295a523f018565e1f0c5ceac3f356 /src | |
parent | f9b1917e8be7a178282514429f494a3905055aab (diff) | |
download | scala-78007ac467c9d6e88ae183a9126772829072704c.tar.gz scala-78007ac467c9d6e88ae183a9126772829072704c.tar.bz2 scala-78007ac467c9d6e88ae183a9126772829072704c.zip |
closes #3619, #4141.
replaced the epic outer.outer.outer by something more robust that goes
to the context corresponding to the enclosing class
nextOuter determines which context is searched next for implicits (after
`this`, which contributes `newImplicits` below) in most cases, it is
simply the outer context if we're owned by a constructor, the actual
current context and the conceptual context are different when it comes
to scoping: the current conceptual scope is the context enclosing the
blocks that represent the constructor body (TODO: why is there more than
one such block in the outer chain?)
review by odersky, extempore
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index e5879c71d6..e53ec4a987 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -113,7 +113,10 @@ trait Contexts { self: Analyzer => var inConstructorSuffix = false // are we in a secondary constructor // after the this constructor call? var returnsSeen = false // for method context: were returns encountered? - var inSelfSuperCall = false // is this a context for a constructor self or super call? + var inSelfSuperCall = false // is this context (enclosed in) a constructor call? + // (the call to the super or self constructor in the first line of a constructor) + // in this context the object's fields should not be in scope + var reportAmbiguousErrors = false var reportGeneralErrors = false var diagnostic: List[String] = Nil // these messages are printed when issuing an error @@ -184,6 +187,7 @@ trait Contexts { self: Analyzer => c.variance = this.variance c.depth = if (scope == this.scope) this.depth else this.depth + 1 c.imports = imports + c.inSelfSuperCall = inSelfSuperCall c.reportAmbiguousErrors = this.reportAmbiguousErrors c.reportGeneralErrors = this.reportGeneralErrors c.diagnostic = this.diagnostic @@ -524,7 +528,17 @@ trait Contexts { self: Analyzer => } def implicitss: List[List[ImplicitInfo]] = { - val nextOuter = if (owner.isConstructor) outer.outer.outer else outer + // nextOuter determines which context is searched next for implicits (after `this`, which contributes `newImplicits` below) + // in most cases, it is simply the outer context + // if we're owned by a constructor, the actual current context and the conceptual context are different when it comes to scoping: + // the current conceptual scope is the context enclosing the blocks that represent the constructor body + // (TODO: why is there more than one such block in the outer chain?) + val scopingCtx = + if(owner.isConstructor) nextEnclosing(c => !c.tree.isInstanceOf[Block]) // drop the constructor body blocks (they come in varying numbers depending on whether we are in the ctor call in the first statement or after) + // scopingCtx == the constructor definition (if we were after the ctor call) or the class that contains this constructor (if we are in the ctor call) + else this + val nextOuter = scopingCtx.outer + if (implicitsRunId != currentRunId) { implicitsRunId = currentRunId implicitsCache = List() @@ -544,8 +558,8 @@ trait Contexts { self: Analyzer => assert(imports.tail == nextOuter.imports) collectImplicitImports(imports.head) } else if (owner.isPackageClass) { - // the corresponding package object may contain implicit members. - collectImplicits(owner.tpe.implicitMembers, owner.tpe) + // the corresponding package object may contain implicit members. + collectImplicits(owner.tpe.implicitMembers, owner.tpe) } else List() implicitsCache = if (newImplicits.isEmpty) nextOuter.implicitss else newImplicits :: nextOuter.implicitss |