summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2017-01-31 10:59:59 -0700
committerJason Zaugg <jzaugg@gmail.com>2017-02-19 11:09:58 +1000
commit06eee798f581ffa21dc4a69974315a7c2bc7abe1 (patch)
tree08a63a02edc5998b4c9eabf9e0ee082d4898baee /src
parentdb8520e5c45d9ce24912849fad16a5c1b54a09b9 (diff)
downloadscala-06eee798f581ffa21dc4a69974315a7c2bc7abe1.tar.gz
scala-06eee798f581ffa21dc4a69974315a7c2bc7abe1.tar.bz2
scala-06eee798f581ffa21dc4a69974315a7c2bc7abe1.zip
Refactor implementation of lookupCompanion
- Check for module class up front to use sourceModule - Consolidate most of the logic in Contexts
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala40
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala9
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala33
3 files changed, 43 insertions, 39 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index d349597b14..7a71561978 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -1193,27 +1193,33 @@ trait Contexts { self: Analyzer =>
res
}
- final def lookupCompanionOf(original: Symbol): Symbol = {
- if (original.isModuleClass) original.sourceModule
- else lookupScopeEntry(original) match {
- case null => NoSymbol
- case entry => entry.owner.lookupCompanion(original)
+ final def lookupCompanionInIncompleteOwner(original: Symbol): Symbol = {
+ /* Search scopes in current and enclosing contexts for the definition of `symbol` */
+ 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
}
- }
- /** 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
+ // 1) Must be owned by the same Scope, to ensure that in
+ // `{ class C; { ...; object C } }`, the class is not seen as a companion of the object.
+ // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions.
+ lookupScopeEntry(original) match {
+ case null => NoSymbol
+ case entry =>
+ def isCompanion(sym: Symbol): Boolean =
+ (original.isModule && sym.isClass || sym.isModule && original.isClass) && sym.isCoDefinedWith(original)
+ entry.owner.lookupNameInSameScopeAs(original, original.name.companionName).filter(isCompanion)
}
- 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 395bda234b..28169c9da1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1955,9 +1955,12 @@ trait Namers extends MethodSynthesis {
// Doing this generally would trigger cycles; that's what we also
// use the lower-level scan through the current Context as a fall back.
if (!currentRun.compiles(owner)) owner.initialize
- original.companionSymbol orElse {
- ctx.lookupCompanionOf(original)
- }
+
+ if (original.isModuleClass) original.sourceModule
+ else if (!owner.isTerm && owner.hasCompleteInfo)
+ original.companionSymbol
+ else
+ ctx.lookupCompanionInIncompleteOwner(original)
}
/** A version of `Symbol#linkedClassOfClass` that works with local companions, ala `companionSymbolOf`. */
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index 51fb31d36d..0435a2c1cf 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -291,25 +291,6 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
null
}
- final def lookupCompanion(original: Symbol): Symbol = {
- lookupSymbolEntry(original) match {
- case null =>
- case entry =>
- 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 companion of the object.
- // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions.
- def isClassAndModule(sym1: Symbol, sym2: Symbol) = sym1.isClass && sym2.isModule
- if ((e.owner eq entry.owner) && (isClassAndModule(original, e.sym) || isClassAndModule(e.sym, original))) {
- return if (e.sym.isCoDefinedWith(original)) e.sym else NoSymbol
- }
- e = lookupNextEntry(e)
- }
- }
- 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
@@ -345,6 +326,20 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
e
}
+ final def lookupNameInSameScopeAs(original: Symbol, companionName: Name): Symbol = {
+ lookupSymbolEntry(original) match {
+ case null =>
+ case entry =>
+ var e = lookupEntry(companionName)
+ while (e != null) {
+ if (e.owner eq entry.owner) return e.sym
+ e = lookupNextEntry(e)
+ }
+ }
+ NoSymbol
+ }
+
+
/** TODO - we can test this more efficiently than checking isSubScope
* in both directions. However the size test might be enough to quickly
* rule out most failures.