Skip to content

Commit 820897b

Browse files
committed
SI-2405 Confer implicit privileges to renamed imports.
Yin and yang would be pleased: A fix in two parts. 1. Use the name of the imported symbol, rather than the alias, in the generated `Select(qual, name)` tree. 2. Do the opposite in `isQualifyingImplicit`, which performs one part of the shadowing check. But there is still work to do. The second part of the shadowing check, `nonImplicitSynonymInScope`, fails to notice this case (irrespective of aliased imports). // Expecting shadowing #2. Alas, none is cast! object Test1 { object A { implicit val x: Int = 1 } import A.x def x: Int = 0 implicitly[Int] } I'm hitching the residual problem to SI-4270's wagon.
1 parent f406550 commit 820897b

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

src/compiler/scala/tools/nsc/typechecker/Contexts.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -598,16 +598,16 @@ trait Contexts { self: Analyzer =>
598598
* it is accessible, and if it is imported there is not already a local symbol
599599
* with the same names. Local symbols override imported ones. This fixes #2866.
600600
*/
601-
private def isQualifyingImplicit(sym: Symbol, pre: Type, imported: Boolean) =
601+
private def isQualifyingImplicit(name: Name, sym: Symbol, pre: Type, imported: Boolean) =
602602
sym.isImplicit &&
603603
isAccessible(sym, pre) &&
604604
!(imported && {
605-
val e = scope.lookupEntry(sym.name)
605+
val e = scope.lookupEntry(name)
606606
(e ne null) && (e.owner == scope)
607607
})
608608

609609
private def collectImplicits(syms: List[Symbol], pre: Type, imported: Boolean = false): List[ImplicitInfo] =
610-
for (sym <- syms if isQualifyingImplicit(sym, pre, imported)) yield
610+
for (sym <- syms if isQualifyingImplicit(sym.name, sym, pre, imported)) yield
611611
new ImplicitInfo(sym.name, pre, sym)
612612

613613
private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = {
@@ -621,7 +621,7 @@ trait Contexts { self: Analyzer =>
621621
var impls = collect(sels1) filter (info => info.name != from)
622622
if (to != nme.WILDCARD) {
623623
for (sym <- imp.importedSymbol(to).alternatives)
624-
if (isQualifyingImplicit(sym, pre, imported = true))
624+
if (isQualifyingImplicit(to, sym, pre, imported = true))
625625
impls = new ImplicitInfo(to, pre, sym) :: impls
626626
}
627627
impls

src/compiler/scala/tools/nsc/typechecker/Implicits.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,11 @@ trait Implicits {
554554

555555
val itree = atPos(pos.focus) {
556556
if (info.pre == NoPrefix) Ident(info.name)
557-
else Select(gen.mkAttributedQualifier(info.pre), info.name)
557+
else {
558+
// SI-2405 Not info.name, which might be an aliased import
559+
val implicitMemberName = info.sym.name
560+
Select(gen.mkAttributedQualifier(info.pre), implicitMemberName)
561+
}
558562
}
559563
printTyping("typedImplicit1 %s, pt=%s, from implicit %s:%s".format(
560564
typeDebug.ptTree(itree), wildPt, info.name, info.tpe)

test/files/neg/t2405.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
t2405.scala:6: warning: imported `y' is permanently hidden by definition of method y
2+
import A.{x => y}
3+
^
4+
t2405.scala:8: error: could not find implicit value for parameter e: Int
5+
implicitly[Int]
6+
^
7+
one warning found
8+
one error found

test/files/neg/t2405.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
object A { implicit val x: Int = 1 }
2+
3+
// Expecting shadowing #1
4+
object Test2 {
5+
{
6+
import A.{x => y}
7+
def y: Int = 0
8+
implicitly[Int]
9+
}
10+
}

test/files/pos/t2405.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
object A { implicit val x: Int = 1 }
2+
3+
// Problem as stated in the ticket.
4+
object Test1 {
5+
import A.{x => y}
6+
implicitly[Int]
7+
}
8+
9+
// Testing for the absense of shadowing #1.
10+
object Test2 {
11+
import A.{x => y}
12+
val x = 2
13+
implicitly[Int]
14+
}
15+
16+
// Testing for the absense of shadowing #2.
17+
object Test3 {
18+
{
19+
import A.{x => y}
20+
def x: Int = 0
21+
implicitly[Int]
22+
}
23+
}

0 commit comments

Comments
 (0)