summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala13
-rw-r--r--test/pending/pos/bug4859.scala15
9 files changed, 55 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index aba17ca290..f5e32fbb09 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -5,12 +5,20 @@
package scala.tools.nsc
-import util.{ FreshNameCreator,Position,NoPosition,SourceFile }
+import util.{ FreshNameCreator, Position, NoPosition, SourceFile, NoSourceFile }
import scala.collection.mutable
import scala.collection.mutable.{ LinkedHashSet, ListBuffer }
trait CompilationUnits { self: Global =>
+ /** An object representing a missing compilation unit.
+ */
+ object NoCompilationUnit extends CompilationUnit(NoSourceFile) {
+ override lazy val isJava = false
+ override def exists = false
+ override def toString() = "NoCompilationUnit"
+ }
+
/** One unit of compilation that has been submitted to the compiler.
* It typically corresponds to a single file of source code. It includes
* error-reporting hooks. */
@@ -25,6 +33,8 @@ trait CompilationUnits { self: Global =>
/** the content of the compilation unit in tree form */
var body: Tree = EmptyTree
+ def exists = source != NoSourceFile && source != null
+
// def parseSettings() = {
// val argsmarker = "SCALAC_ARGS"
// if(comments nonEmpty) {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 76af2a7a03..75019f7624 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -48,7 +48,7 @@ abstract class GenICode extends SubComponent {
override def description = "Generate ICode from the AST"
- var unit: CompilationUnit = _
+ var unit: CompilationUnit = NoCompilationUnit
override def run() {
scalaPrimitives.init
@@ -61,7 +61,7 @@ abstract class GenICode extends SubComponent {
unit.icode.clear
informProgress("Generating icode for " + unit)
gen(unit.body)
- this.unit = null
+ this.unit = NoCompilationUnit
}
def gen(tree: Tree): Context = gen(tree, new Context())
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index fc53a34c45..3d7d14627c 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -205,7 +205,7 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
*/
override def signalDone(context: Context, old: Tree, result: Tree) {
if (interruptsEnabled && analyzer.lockedCount == 0) {
- if (context.unit != null &&
+ if (context.unit.exists &&
result.pos.isOpaqueRange &&
(result.pos includes context.unit.targetPos)) {
var located = new TypedLocator(context.unit.targetPos) locateIn result
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 96b27b58ae..44c28cf2f5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -21,6 +21,7 @@ trait Contexts { self: Analyzer =>
val NoContext = new Context {
override def implicitss: List[List[ImplicitInfo]] = List()
outer = this
+ override def toString = "NoContext"
}
NoContext.enclClass = NoContext
NoContext.enclMethod = NoContext
@@ -89,7 +90,7 @@ trait Contexts { self: Analyzer =>
}
class Context private[typechecker] {
- var unit: CompilationUnit = _
+ var unit: CompilationUnit = NoCompilationUnit
var tree: Tree = _ // Tree associated with this context
var owner: Symbol = NoSymbol // The current owner
var scope: Scope = _ // The current scope
@@ -164,12 +165,11 @@ trait Contexts { self: Analyzer =>
*/
def make(unit: CompilationUnit, tree: Tree, owner: Symbol,
scope: Scope, imports: List[ImportInfo]): Context = {
- val c = new Context
- c.unit = unit
- c.tree = tree
+ val c = new Context
+ c.unit = unit
+ c.tree = tree
c.owner = owner
c.scope = scope
-
c.outer = this
tree match {
@@ -203,6 +203,7 @@ trait Contexts { self: Analyzer =>
c.retyping = this.retyping
c.openImplicits = this.openImplicits
registerContext(c.asInstanceOf[analyzer.Context])
+ debuglog("Created context: " + this + " ==> " + c)
c
}
@@ -364,11 +365,9 @@ trait Contexts { self: Analyzer =>
def nextEnclosing(p: Context => Boolean): Context =
if (this == NoContext || p(this)) this else outer.nextEnclosing(p)
- override def toString = (
- if (this == NoContext) "NoContext"
- else "Context(%s@%s scope=%s)".format(owner.fullName, tree.getClass.getName split "[.$]" last, scope.##)
+ override def toString = "Context(%s@%s unit=%s scope=%s)".format(
+ owner.fullName, tree.shortClass, unit, scope.##
)
-
/** Is `sub` a subclass of `base` or a companion object of such a subclass?
*/
def isSubClassOrCompanion(sub: Symbol, base: Symbol) =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 2a6fc122e2..7305cef34f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -249,7 +249,7 @@ trait Infer {
tree setSymbol sym setType ErrorType
} else {
val topClass = context.owner.toplevelClass
- if (context.unit != null)
+ if (context.unit.exists)
context.unit.depends += sym.toplevelClass
var sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 513522e017..2c424d17d7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -414,7 +414,7 @@ trait TypeDiagnostics {
// Error suppression will squash some of these warnings unless we circumvent it.
// It is presumed if you are using a -Y option you would really like to hear
// the warnings you've requested.
- if (settings.warnDeadCode.value && context.unit != null && treeOK(tree) && exprOK) {
+ if (settings.warnDeadCode.value && context.unit.exists && treeOK(tree) && exprOK) {
val saved = context.reportGeneralErrors
try {
context.reportGeneralErrors = true
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d8c09cc685..f305644837 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2101,7 +2101,7 @@ trait Typers extends Modes with Adaptations {
def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
val inBlock = exprOwner == context.owner
def includesTargetPos(tree: Tree) =
- tree.pos.isRange && context.unit != null && (tree.pos includes context.unit.targetPos)
+ tree.pos.isRange && context.unit.exists && (tree.pos includes context.unit.targetPos)
val localTarget = stats exists includesTargetPos
def typedStat(stat: Tree): Tree = {
if (context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(stat))
@@ -3779,7 +3779,7 @@ trait Typers extends Modes with Adaptations {
// compilation units. Defined symbols take precedence over erroneous imports.
if (defSym.definedInPackage &&
(!currentRun.compiles(defSym) ||
- (context.unit ne null) && defSym.sourceFile != context.unit.source.file))
+ context.unit.exists && defSym.sourceFile != context.unit.source.file))
defSym = NoSymbol
else if (impSym.isError || impSym.name == nme.CONSTRUCTOR)
impSym = NoSymbol
@@ -4328,8 +4328,7 @@ trait Typers extends Modes with Adaptations {
case ex: Exception =>
if (settings.debug.value) // @M causes cyclic reference error
Console.println("exception when typing "+tree+", pt = "+pt)
- if ((context ne null) && (context.unit ne null) &&
- (context.unit.source ne null) && (tree ne null))
+ if (context != null && context.unit.exists && tree != null)
logError("AT: " + (tree.pos).dbgString, ex)
throw ex
}
diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala
index 44e06441ce..42489c5aaf 100644
--- a/src/compiler/scala/tools/nsc/util/SourceFile.scala
+++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala
@@ -51,6 +51,19 @@ abstract class SourceFile {
def identifier(pos: Position): Option[String] = None
}
+/** An object representing a missing source file.
+ */
+object NoSourceFile extends SourceFile {
+ def content = Array()
+ def file = null // TODO: push NPE-defense out another level or two
+ def isLineBreak(idx: Int) = false
+ def isSelfContained = true
+ def length = -1
+ def offsetToLine(offset: Int) = -1
+ def lineToOffset(index : Int) = -1
+ override def toString = "NoSourceFile"
+}
+
object ScriptSourceFile {
/** Length of the script header from the given content, if there is one.
* The header begins with "#!" or "::#!" and ends with a line starting
diff --git a/test/pending/pos/bug4859.scala b/test/pending/pos/bug4859.scala
new file mode 100644
index 0000000000..ec5abd966d
--- /dev/null
+++ b/test/pending/pos/bug4859.scala
@@ -0,0 +1,15 @@
+object O {
+ C().CC()
+ D().DD()
+}
+
+case class C() {
+ case class CC()
+}
+
+case class D() {
+ class DD()
+ object DD {
+ def apply() = new DD()
+ }
+}