summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2011-01-26 07:34:03 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2011-01-26 07:34:03 +0000
commit78007ac467c9d6e88ae183a9126772829072704c (patch)
tree25a9e8060fc295a523f018565e1f0c5ceac3f356 /src/compiler/scala/tools/nsc/typechecker/Contexts.scala
parentf9b1917e8be7a178282514429f494a3905055aab (diff)
downloadscala-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/compiler/scala/tools/nsc/typechecker/Contexts.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala22
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