summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-11-17 12:49:59 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-11-29 15:43:36 +1000
commit37037fe70651eee7a1e8a77a2f8b6e74968836b6 (patch)
tree0b996ec1bc2e6fb84939c07782be6f5116e8553c /src/reflect
parent3107532f459d4a66ecd302f0b39b14bd7cf2d248 (diff)
downloadscala-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.scala29
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