summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2010-01-13 16:36:06 +0000
committerMartin Odersky <odersky@gmail.com>2010-01-13 16:36:06 +0000
commitfa0cdc7b3f33449c8cc253ec45b281e9c4cb28b2 (patch)
treee91e7b4fa56e1fa90976656ac9be908ed558a4fb /src/compiler
parentd64620b254491b38b7cc6ce600ba2256ce5ef6a8 (diff)
downloadscala-fa0cdc7b3f33449c8cc253ec45b281e9c4cb28b2.tar.gz
scala-fa0cdc7b3f33449c8cc253ec45b281e9c4cb28b2.tar.bz2
scala-fa0cdc7b3f33449c8cc253ec45b281e9c4cb28b2.zip
Closes #2866, #2870.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala38
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala11
2 files changed, 36 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 2acc09b70e..dd592bb96d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -180,7 +180,7 @@ trait Contexts { self: Analyzer =>
scope: Scope, imports: List[ImportInfo]): Context = {
val c = new Context
c.unit = unit
- c.tree = sanitize(tree)
+ c.tree = /*sanitize*/(tree) // used to be for IDE
c.owner = owner
c.scope = scope
@@ -464,20 +464,35 @@ trait Contexts { self: Analyzer =>
implicitsCache = null
if (outer != null && outer != this) outer.resetCache
}
- private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] =
- for (sym <- syms if sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))
+
+ /** A symbol `sym` qualifies as an implicit if it has the IMPLICIT flag set,
+ * 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) =
+ sym.hasFlag(IMPLICIT) &&
+ isAccessible(sym, pre, false) &&
+ !(imported && {
+ val e = scope.lookupEntry(sym.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 new ImplicitInfo(sym.name, pre, sym)
private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = {
val pre = imp.qual.tpe
def collect(sels: List[ImportSelector]): List[ImplicitInfo] = sels match {
- case List() => List()
- case List(ImportSelector(nme.WILDCARD, _, _, _)) => collectImplicits(pre.implicitMembers, pre)
+ case List() =>
+ List()
+ case List(ImportSelector(nme.WILDCARD, _, _, _)) =>
+ collectImplicits(pre.implicitMembers, pre, imported = true)
case ImportSelector(from, _, to, _) :: sels1 =>
var impls = collect(sels1) filter (info => info.name != from)
if (to != nme.WILDCARD) {
for (sym <- imp.importedSymbol(to).alternatives)
- if (sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))
+ if (isQualifyingImplicit(sym, pre, imported = true))
impls = new ImplicitInfo(to, pre, sym) :: impls
}
impls
@@ -488,7 +503,6 @@ trait Contexts { self: Analyzer =>
def implicitss: List[List[ImplicitInfo]] = {
val nextOuter = if (owner.isConstructor) outer.outer.outer else outer
- // can we can do something smarter to bring back the implicit cache?
if (implicitsRunId != currentRunId) {
implicitsRunId = currentRunId
implicitsCache = List()
@@ -545,7 +559,7 @@ trait Contexts { self: Analyzer =>
/** The prefix expression */
def qual: Tree = tree.symbol.info match {
case ImportType(expr) => expr
- case ErrorType => tree
+ case ErrorType => tree setType NoType // fix for #2870
case _ => throw new FatalError("symbol " + tree.symbol + " has bad type: " + tree.symbol.info);//debug
}
@@ -561,16 +575,16 @@ trait Contexts { self: Analyzer =>
var renamed = false
var selectors = tree.selectors
while (selectors != Nil && result == NoSymbol) {
- if (selectors.head.name != nme.WILDCARD)
- notifyImport(name, qual.tpe, selectors.head.name, selectors.head.rename)
+// if (selectors.head.name != nme.WILDCARD) // used to be for IDE
+// notifyImport(name, qual.tpe, selectors.head.name, selectors.head.rename)
if (selectors.head.rename == name.toTermName)
- result = qual.tpe.member(
+ result = qual.tpe.nonLocalMember( // new to address #2733: consider only non-local members for imports
if (name.isTypeName) selectors.head.name.toTypeName else selectors.head.name)
else if (selectors.head.name == name.toTermName)
renamed = true
else if (selectors.head.name == nme.WILDCARD && !renamed)
- result = qual.tpe.member(name)
+ result = qual.tpe.nonLocalMember(name)
selectors = selectors.tail
}
result
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 1955348f91..4b5b052dcb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1188,8 +1188,17 @@ trait Namers { self: Analyzer =>
def checkSelectors(selectors: List[ImportSelector]): Unit = selectors match {
case ImportSelector(from, _, to, _) :: rest =>
if (from != nme.WILDCARD && base != ErrorType) {
- if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol)
+ if (base.member(from) == NoSymbol &&
+ base.member(from.toTypeName) == NoSymbol)
context.error(tree.pos, from.decode + " is not a member of " + expr);
+/* The previous test should be:
+ if (base.nonLocalMember(from) == NoSymbol &&
+ base.nonLocalMember(from.toTypeName) == NoSymbol)
+ context.error(tree.pos, from.decode + " is not a member of " + expr);
+
+ * but this breaks the jvm/interpreter.scala test, because
+ * it seems it imports a local member of a $iw object
+ */
if (checkNotRedundant(tree.pos, from, to))
checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName)
}