summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-12-23 20:09:54 +0000
committerMartin Odersky <odersky@gmail.com>2009-12-23 20:09:54 +0000
commitb858cef58795459435c10fa06e5db8f2e6d9ca8e (patch)
tree8bba393007a48de2c34b0067ef7654f2c4a6d7ac /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent17f712ec18b4f6f4fac43f146b66c749ed68caa7 (diff)
downloadscala-b858cef58795459435c10fa06e5db8f2e6d9ca8e.tar.gz
scala-b858cef58795459435c10fa06e5db8f2e6d9ca8e.tar.bz2
scala-b858cef58795459435c10fa06e5db8f2e6d9ca8e.zip
a more thorough treatment of the stale symbol p...
a more thorough treatment of the stale symbol problem. review by milessabin.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala44
1 files changed, 25 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ec5ce91f3c..0e756308c3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -545,6 +545,24 @@ trait Typers { self: Analyzer =>
final val xtypes = false
+ /** Is symbol defined and not stale?
+ */
+ def reallyExists(sym: Symbol) = {
+ if (isStale(sym)) sym.setInfo(NoType)
+ sym.exists
+ }
+
+ /** A symbol is stale if it is toplevel, to be loaded from a classfile, and
+ * the classfile is produced from a sourcefile which is compiled in the current run.
+ */
+ def isStale(sym: Symbol): Boolean = {
+ sym.rawInfo.isInstanceOf[loaders.ClassfileLoader] && {
+ sym.rawInfo.load(sym)
+ (sym.sourceFile ne null) &&
+ (currentRun.compiledFiles contains sym.sourceFile)
+ }
+ }
+
/** Does the context of tree <code>tree</code> require a stable type?
*/
private def isStableContext(tree: Tree, mode: Int, pt: Type) =
@@ -895,7 +913,7 @@ trait Typers { self: Analyzer =>
case _ => TypeTree(tree.tpe) setOriginal(tree)
}
} else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) { // (5)
- val extractor = tree.symbol.filter(sym => unapplyMember(sym.tpe).exists)
+ val extractor = tree.symbol.filter(sym => reallyExists(unapplyMember(sym.tpe)))
if (extractor != NoSymbol) {
tree setSymbol extractor
val unapply = unapplyMember(extractor.tpe)
@@ -1655,11 +1673,11 @@ trait Typers { self: Analyzer =>
while (cx != NoContext) {
val pre = cx.enclClass.prefix
val defEntry = cx.scope.lookupEntry(name)
- if ((defEntry ne null) && defEntry.sym.exists)
+ if ((defEntry ne null) && reallyExists(defEntry.sym))
return Some(defEntry.sym)
cx = cx.enclClass
- (pre member name filter (sym => sym.exists && context.isAccessible(sym, pre, false))) match {
+ (pre member name filter (sym => reallyExists(sym) && context.isAccessible(sym, pre, false))) match {
case NoSymbol => cx = cx.outer
case other => return Some(other)
}
@@ -3467,7 +3485,7 @@ trait Typers { self: Analyzer =>
val qual1 = adaptToName(qual, name)
if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
- if (!sym.exists) {
+ if (!reallyExists(sym)) {
if (settings.debug.value) Console.err.println("qual = "+qual+":"+qual.tpe+"\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+"\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+"\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner)
if (!qual.tpe.widen.isErroneous) {
error(tree.pos,
@@ -3534,25 +3552,13 @@ trait Typers { self: Analyzer =>
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
var qual: Tree = EmptyTree // the qualififier tree if transformed tree is a select
- // a symbol is stale if it is toplevel, to be loaded from a classfile, and
- // the classfile is produced from a sourcefile which is compiled in the current run.
- def isStale(sym: Symbol): Boolean = {
- sym.owner.isPackageClass &&
- sym.rawInfo.isInstanceOf[loaders.ClassfileLoader] && {
- sym.rawInfo.load(sym)
- (sym.sourceFile ne null) &&
- (currentRun.compiledFiles contains sym.sourceFile)
- }
- }
-
// A symbol qualifies if it exists and is not stale. Stale symbols
// are made to disappear here. In addition,
// if we are in a constructor of a pattern, we ignore all definitions
// which are methods (note: if we don't do that
// case x :: xs in class List would return the :: method).
def qualifies(sym: Symbol): Boolean = {
- if (isStale(sym)) sym.setInfo(NoType)
- sym.exists &&
+ reallyExists(sym) &&
((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod)
}
@@ -3584,7 +3590,7 @@ trait Typers { self: Analyzer =>
else cx.depth - (cx.scope.nestingLevel - defEntry.owner.nestingLevel)
var impSym: Symbol = NoSymbol; // the imported symbol
var imports = context.imports; // impSym != NoSymbol => it is imported from imports.head
- while (!impSym.exists && !imports.isEmpty && imports.head.depth > symDepth) {
+ while (!reallyExists(impSym) && !imports.isEmpty && imports.head.depth > symDepth) {
impSym = imports.head.importedSymbol(name)
if (!impSym.exists) imports = imports.tail
}
@@ -3626,7 +3632,7 @@ trait Typers { self: Analyzer =>
(!imports.head.isExplicitImport(name) ||
imports1.head.depth == imports.head.depth)) {
var impSym1 = imports1.head.importedSymbol(name)
- if (impSym1.exists) {
+ if (reallyExists(impSym1)) {
if (imports1.head.isExplicitImport(name)) {
if (imports.head.isExplicitImport(name) ||
imports1.head.depth != imports.head.depth) ambiguousImport()