From 2d8f919389fa33a554c5fb828bfa040f1b2531e4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 25 Sep 2014 11:05:09 +1000 Subject: 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. --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala') diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index b85c8e6d42..2fab4557bd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1012,11 +1012,14 @@ trait Implicits { } case None => if (pre.isStable && !pre.typeSymbol.isExistentiallyBound) { - val companion = companionSymbolOf(sym, context) + val companion = + if (sym.isPackageClass) sym.info.member(nme.PACKAGE) //companionSymbolOf(sym.member, context) + else companionSymbolOf(sym, context) companion.moduleClass match { case mc: ModuleClassSymbol => + val pre1 = if (mc.isPackageObjectClass) mc.typeOfThis else singleType(pre, companion) val infos = - for (im <- mc.implicitMembers.toList) yield new ImplicitInfo(im.name, singleType(pre, companion), im) + for (im <- mc.implicitMembers.toList) yield new ImplicitInfo(im.name, pre1, im) if (infos.nonEmpty) infoMap += (sym -> infos) case _ => -- cgit v1.2.3