diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-11-17 12:49:59 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-11-29 15:43:36 +1000 |
commit | 37037fe70651eee7a1e8a77a2f8b6e74968836b6 (patch) | |
tree | 0b996ec1bc2e6fb84939c07782be6f5116e8553c /src/compiler/scala/tools/nsc/typechecker/Contexts.scala | |
parent | 3107532f459d4a66ecd302f0b39b14bd7cf2d248 (diff) | |
download | scala-37037fe70651eee7a1e8a77a2f8b6e74968836b6.tar.gz scala-37037fe70651eee7a1e8a77a2f8b6e74968836b6.tar.bz2 scala-37037fe70651eee7a1e8a77a2f8b6e74968836b6.zip |
SI-3772 Fix detection of term-owned companions
Companion detection consults the scopes of enclosing Contexts during
typechecking to avoid the cycles that would ensue if we had to look
at into the info of enclosing class symbols. For example, this used
to typecheck:
object CC { val outer = 42 }
if ("".isEmpty) {
case class CC(c: Int)
CC.outer
}
This logic was not suitably hardened to find companions in exactly
the same nesting level.
After fixing this problem, a similar problem in `Namer::inCurrentScope`
could be solved to be more selective about synthesizing a companion
object. In particular, if a manually defined companion trails after
the case class, don't create an addiotional synthetic comanpanion object.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Contexts.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 21 |
1 files changed, 21 insertions, 0 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 */ |