Skip to content
Browse files

SI-7429 Fix checkinit build failure in Contexts

The recent refactoring in Contexts resulted in an uninitialized
field access. This wasn't deadly, as it was already compensating
for this by expecting a null value for `outer` during in the body
of the constructor of Contexts when extended by NoContext.

This commit reworks that code a little to avoid dereferencing the
overriden `outer` field.

A similar mistake in `ImportContext` is also corrected.
  • Loading branch information...
1 parent 464c9fe commit f59be7a7838d763de4b49e5be6b848754f1f7c17 @retronym retronym committed Apr 28, 2013
Showing with 13 additions and 21 deletions.
  1. +13 −21 src/compiler/scala/tools/nsc/typechecker/Contexts.scala
View
34 src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -21,10 +21,7 @@ trait Contexts { self: Analyzer =>
object NoContext
extends Context(EmptyTree, NoSymbol, EmptyScope, NoCompilationUnit,
- outer = null /*We can't pass NoContext here, overriden below*/) {
-
- override val outer = this
-
+ null) { // We can't pass the uninitialized `this`. Instead, we treat null specially in `Context#outer`
enclClass = this
enclMethod = this
@@ -161,10 +158,13 @@ trait Contexts { self: Analyzer =>
* @param tree Tree associated with this context
* @param owner The current owner
* @param scope The current scope
- * @param outer The next outer context.
+ * @param _outer The next outer context.
*/
class Context private[typechecker](val tree: Tree, val owner: Symbol, val scope: Scope,
- val unit: CompilationUnit, val outer: Context) {
+ val unit: CompilationUnit, _outer: Context) {
+ private def outerIsNoContext = _outer eq null
+ final def outer: Context = if (outerIsNoContext) NoContext else _outer
+
/** The next outer context whose tree is a template or package definition */
var enclClass: Context = _
@@ -199,9 +199,10 @@ trait Contexts { self: Analyzer =>
private var _undetparams: List[Symbol] = List()
+ protected def outerDepth = if (outerIsNoContext) 0 else outer.depth
+
val depth: Int = {
- val increasesDepth = isRootImport || (outer eq null) || (outer.scope != scope)
- def outerDepth = if (outer eq null) 0 else outer.depth
+ val increasesDepth = isRootImport || outerIsNoContext || (outer.scope != scope)
( if (increasesDepth) 1 else 0 ) + outerDepth
}
@@ -1138,22 +1139,15 @@ trait Contexts { self: Analyzer =>
/** A `Context` focussed on an `Import` tree */
trait ImportContext extends Context {
- private def makeImpInfo = {
- val info = new ImportInfo(tree.asInstanceOf[Import], outer.depth)
- if (settings.lint && !info.isRootImport) // excludes java.lang/scala/Predef imports
+ private val impInfo: ImportInfo = {
+ val info = new ImportInfo(tree.asInstanceOf[Import], outerDepth)
+ if (settings.lint && !isRootImport) // excludes java.lang/scala/Predef imports
allImportInfos(unit) ::= info
info
}
-
- private var _impInfo: ImportInfo = null // hand rolled lazy val, we don't need/want synchronization.
- private def impInfo: ImportInfo = {
- if (_impInfo eq null) _impInfo = makeImpInfo
- _impInfo
- }
-
override final def imports = impInfo :: super.imports
override final def firstImport = Some(impInfo)
- override final def isRootImport = impInfo.isRootImport
+ override final def isRootImport = !tree.pos.isDefined
override final def toString = s"ImportContext { $impInfo; outer.owner = ${outer.owner} }"
}
@@ -1227,8 +1221,6 @@ trait Contexts { self: Analyzer =>
def isExplicitImport(name: Name): Boolean =
tree.selectors exists (_.rename == name.toTermName)
- final def isRootImport: Boolean = !tree.pos.isDefined
-
/** The symbol with name `name` imported from import clause `tree`.
*/
def importedSymbol(name: Name): Symbol = importedSymbol(name, requireExplicit = false)

0 comments on commit f59be7a

Please sign in to comment.
Something went wrong with that request. Please try again.