diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 21 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 10 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Scopes.scala | 29 |
3 files changed, 55 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index c73ea54c3d..cbe9e522a2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1192,6 +1192,27 @@ trait Contexts { self: Analyzer => } res } + + final def lookupCompanionOf(original: Symbol): Symbol = { + lookupScopeEntry(original) match { + case null => NoSymbol + case entry => entry.owner.lookupCompanion(original).filter(_.isCoDefinedWith(original)) + } + } + + /** Search scopes in current and enclosing contexts for the definition of `symbol` */ + private def lookupScopeEntry(symbol: Symbol): ScopeEntry = { + var res: ScopeEntry = null + var ctx = this + while (res == null && ctx.outer != ctx) { + val s = ctx.scope lookupSymbolEntry symbol + if (s != null) + res = s + else + ctx = ctx.outer + } + res + } } //class Context /** A `Context` focussed on an `Import` tree */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 78e8c8c073..60bda3ff9f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -220,7 +220,10 @@ trait Namers extends MethodSynthesis { private def inCurrentScope(m: Symbol): Boolean = { if (owner.isClass) owner == m.owner - else m.owner.isClass && context.scope == m.owner.info.decls + else context.scope.lookupSymbolEntry(m) match { + case null => false + case entry => entry.owner eq context.scope + } } /** Enter symbol into context's scope and return symbol itself */ @@ -1923,10 +1926,7 @@ trait Namers extends MethodSynthesis { // use the lower-level scan through the current Context as a fall back. if (!currentRun.compiles(owner)) owner.initialize original.companionSymbol orElse { - ctx.lookup(original.name.companionName, owner).suchThat(sym => - (original.isTerm || sym.hasModuleFlag) && - (sym isCoDefinedWith original) - ) + ctx.lookupCompanionOf(original) } } diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index a7bb127506..0df8358d7d 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -282,6 +282,35 @@ trait Scopes extends api.Scopes { self: SymbolTable => } } + final def lookupSymbolEntry(sym: Symbol): ScopeEntry = { + var e = lookupEntry(sym.name) + while (e ne null) { + if (e.sym == sym) return e + e = lookupNextEntry(e) + } + null + } + + final def lookupCompanion(original: Symbol): Symbol = { + lookupSymbolEntry(original) match { + case null => + case entry if entry.sym == original => + var e = lookupEntry(original.name.companionName) + while (e != null) { + // 1) Must be owned by the same Scope, to ensure that in + // `{ class C; { ...; object C } }`, the class is not seen as a comaniopn of the object. + // 2) Must be in exactly the same scope, so that `{ class C; def C }` are not companions + // TODO Exclude type aliases as companions of terms? + if ((e.owner eq entry.owner) && (original.isTerm || e.sym.hasModuleFlag)) { + return e.sym + } + e = lookupNextEntry(e) + } + case _ => + } + NoSymbol + } + /** lookup a symbol entry matching given name. * @note from Martin: I believe this is a hotspot or will be one * in future versions of the type system. I have reverted the previous |