diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2012-05-22 00:34:06 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2012-05-22 08:07:34 +0200 |
commit | 820897b978ee6837ca463b186bab0f6349807c18 (patch) | |
tree | d97ec24f78165a1ac6be704630176927f94ff6c9 | |
parent | f406550146250f5a6036d3d778582efa6d68252a (diff) | |
download | scala-820897b978ee6837ca463b186bab0f6349807c18.tar.gz scala-820897b978ee6837ca463b186bab0f6349807c18.tar.bz2 scala-820897b978ee6837ca463b186bab0f6349807c18.zip |
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.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 6 | ||||
-rw-r--r-- | test/files/neg/t2405.check | 8 | ||||
-rw-r--r-- | test/files/neg/t2405.scala | 10 | ||||
-rw-r--r-- | test/files/pos/t2405.scala | 23 |
5 files changed, 50 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 0924789948..83be4a0b38 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -598,16 +598,16 @@ trait Contexts { self: Analyzer => * it is accessible, and if it is imported there is not already a local symbol * with the same names. Local symbols override imported ones. This fixes #2866. */ - private def isQualifyingImplicit(sym: Symbol, pre: Type, imported: Boolean) = + private def isQualifyingImplicit(name: Name, sym: Symbol, pre: Type, imported: Boolean) = sym.isImplicit && isAccessible(sym, pre) && !(imported && { - val e = scope.lookupEntry(sym.name) + val e = scope.lookupEntry(name) (e ne null) && (e.owner == scope) }) private def collectImplicits(syms: List[Symbol], pre: Type, imported: Boolean = false): List[ImplicitInfo] = - for (sym <- syms if isQualifyingImplicit(sym, pre, imported)) yield + for (sym <- syms if isQualifyingImplicit(sym.name, sym, pre, imported)) yield new ImplicitInfo(sym.name, pre, sym) private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = { @@ -621,7 +621,7 @@ trait Contexts { self: Analyzer => var impls = collect(sels1) filter (info => info.name != from) if (to != nme.WILDCARD) { for (sym <- imp.importedSymbol(to).alternatives) - if (isQualifyingImplicit(sym, pre, imported = true)) + if (isQualifyingImplicit(to, sym, pre, imported = true)) impls = new ImplicitInfo(to, pre, sym) :: impls } impls diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 8f025336bb..b2d373593f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -554,7 +554,11 @@ trait Implicits { val itree = atPos(pos.focus) { if (info.pre == NoPrefix) Ident(info.name) - else Select(gen.mkAttributedQualifier(info.pre), info.name) + else { + // SI-2405 Not info.name, which might be an aliased import + val implicitMemberName = info.sym.name + Select(gen.mkAttributedQualifier(info.pre), implicitMemberName) + } } printTyping("typedImplicit1 %s, pt=%s, from implicit %s:%s".format( typeDebug.ptTree(itree), wildPt, info.name, info.tpe) diff --git a/test/files/neg/t2405.check b/test/files/neg/t2405.check new file mode 100644 index 0000000000..78360bcc21 --- /dev/null +++ b/test/files/neg/t2405.check @@ -0,0 +1,8 @@ +t2405.scala:6: warning: imported `y' is permanently hidden by definition of method y + import A.{x => y} + ^ +t2405.scala:8: error: could not find implicit value for parameter e: Int + implicitly[Int] + ^ +one warning found +one error found diff --git a/test/files/neg/t2405.scala b/test/files/neg/t2405.scala new file mode 100644 index 0000000000..6982285b98 --- /dev/null +++ b/test/files/neg/t2405.scala @@ -0,0 +1,10 @@ +object A { implicit val x: Int = 1 } + +// Expecting shadowing #1 +object Test2 { + { + import A.{x => y} + def y: Int = 0 + implicitly[Int] + } +} diff --git a/test/files/pos/t2405.scala b/test/files/pos/t2405.scala new file mode 100644 index 0000000000..224b2ce83b --- /dev/null +++ b/test/files/pos/t2405.scala @@ -0,0 +1,23 @@ +object A { implicit val x: Int = 1 } + +// Problem as stated in the ticket. +object Test1 { + import A.{x => y} + implicitly[Int] +} + +// Testing for the absense of shadowing #1. +object Test2 { + import A.{x => y} + val x = 2 + implicitly[Int] +} + +// Testing for the absense of shadowing #2. +object Test3 { + { + import A.{x => y} + def x: Int = 0 + implicitly[Int] + } +} |