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/reflect | |
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/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/Scopes.scala | 29 |
1 files changed, 29 insertions, 0 deletions
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 |