diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-09-25 11:05:09 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-11-07 11:40:03 +1000 |
commit | 2d8f919389fa33a554c5fb828bfa040f1b2531e4 (patch) | |
tree | e1286b71effedc5104d07348b54eebe37dc456ab /src/reflect/scala/reflect/internal/Symbols.scala | |
parent | c12a9b7bf8dc423783dd02eb0e4c477c86de96df (diff) | |
download | scala-2d8f919389fa33a554c5fb828bfa040f1b2531e4.tar.gz scala-2d8f919389fa33a554c5fb828bfa040f1b2531e4.tar.bz2 scala-2d8f919389fa33a554c5fb828bfa040f1b2531e4.zip |
SI-8862 Fix treatment of inherited implicits in package objects
Two spots in implicit search fell prey to a trap with package
objects. Members of a package object are entered into the scope
of the enclosing package, but that doesn't form a suitable prefix
for determing the member type.
A REPL transcript paints a picture that speaks a 1000 words:
```
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package p { class C[A] { def foo: A = ??? }; object `package` extends C[String] }
// Exiting paste mode, now interpreting.
scala> val p = rootMirror.getPackageIfDefined("p")
warning: there was one deprecation warning; re-run with -deprecation for details
p: $r.intp.global.Symbol = package p
scala> p.info.decls
res0: $r.intp.global.Scope = Scopes(class C, package object p, method foo)
scala> val foo = p.info.decl(TermName("foo"))
foo: $r.intp.global.Symbol = method foo
scala> p.typeOfThis memberType foo
res1: $r.intp.global.Type = => A
scala> val fooOwner = foo.owner
fooOwner: $r.intp.global.Symbol = class C
scala> p.info.decl(nme.PACKAGE).typeOfThis memberType foo
res3: $r.intp.global.Type = => String
```
This commit detects if we find an implicit in a package module,
and then uses the self type of the corresponding package object
as the prefix for the `ImplicitInfo`. This is done in both
`Context.implicitss` (which collects in-scope implicits), and
in `companionImplicitMap` (which harvests them from the implicit
scope.) In addition, it was necessary / possible to remove a special
case that excluded package object implicits, the referenced tests for
SI-3999 now pass without this.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Symbols.scala')
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 10 |
1 files changed, 3 insertions, 7 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 44fce2c9ab..8a2b51bde8 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3357,13 +3357,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def implicitMembers: Scope = { val tp = info if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) { - // Skip a package object class, because the members are also in - // the package and we wish to avoid spurious ambiguities as in pos/t3999. - if (!isPackageObjectClass) { - implicitMembersCacheValue = tp.implicitMembers - implicitMembersCacheKey1 = tp - implicitMembersCacheKey2 = tp.decls.elems - } + implicitMembersCacheValue = tp.implicitMembers + implicitMembersCacheKey1 = tp + implicitMembersCacheKey2 = tp.decls.elems } implicitMembersCacheValue } |