Skip to content

Commit fa0cdc7

Browse files
committed
1 parent d64620b commit fa0cdc7

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

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

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ trait Contexts { self: Analyzer =>
180180
scope: Scope, imports: List[ImportInfo]): Context = {
181181
val c = new Context
182182
c.unit = unit
183-
c.tree = sanitize(tree)
183+
c.tree = /*sanitize*/(tree) // used to be for IDE
184184
c.owner = owner
185185
c.scope = scope
186186

@@ -464,20 +464,35 @@ trait Contexts { self: Analyzer =>
464464
implicitsCache = null
465465
if (outer != null && outer != this) outer.resetCache
466466
}
467-
private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] =
468-
for (sym <- syms if sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))
467+
468+
/** A symbol `sym` qualifies as an implicit if it has the IMPLICIT flag set,
469+
* it is accessible, and if it is imported there is not already a local symbol
470+
* with the same names. Local symbols override imported ones. This fixes #2866.
471+
*/
472+
private def isQualifyingImplicit(sym: Symbol, pre: Type, imported: Boolean) =
473+
sym.hasFlag(IMPLICIT) &&
474+
isAccessible(sym, pre, false) &&
475+
!(imported && {
476+
val e = scope.lookupEntry(sym.name)
477+
(e ne null) && (e.owner == scope)
478+
})
479+
480+
private def collectImplicits(syms: List[Symbol], pre: Type, imported: Boolean = false): List[ImplicitInfo] =
481+
for (sym <- syms if isQualifyingImplicit(sym, pre, imported))
469482
yield new ImplicitInfo(sym.name, pre, sym)
470483

471484
private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = {
472485
val pre = imp.qual.tpe
473486
def collect(sels: List[ImportSelector]): List[ImplicitInfo] = sels match {
474-
case List() => List()
475-
case List(ImportSelector(nme.WILDCARD, _, _, _)) => collectImplicits(pre.implicitMembers, pre)
487+
case List() =>
488+
List()
489+
case List(ImportSelector(nme.WILDCARD, _, _, _)) =>
490+
collectImplicits(pre.implicitMembers, pre, imported = true)
476491
case ImportSelector(from, _, to, _) :: sels1 =>
477492
var impls = collect(sels1) filter (info => info.name != from)
478493
if (to != nme.WILDCARD) {
479494
for (sym <- imp.importedSymbol(to).alternatives)
480-
if (sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))
495+
if (isQualifyingImplicit(sym, pre, imported = true))
481496
impls = new ImplicitInfo(to, pre, sym) :: impls
482497
}
483498
impls
@@ -488,7 +503,6 @@ trait Contexts { self: Analyzer =>
488503

489504
def implicitss: List[List[ImplicitInfo]] = {
490505
val nextOuter = if (owner.isConstructor) outer.outer.outer else outer
491-
// can we can do something smarter to bring back the implicit cache?
492506
if (implicitsRunId != currentRunId) {
493507
implicitsRunId = currentRunId
494508
implicitsCache = List()
@@ -545,7 +559,7 @@ trait Contexts { self: Analyzer =>
545559
/** The prefix expression */
546560
def qual: Tree = tree.symbol.info match {
547561
case ImportType(expr) => expr
548-
case ErrorType => tree
562+
case ErrorType => tree setType NoType // fix for #2870
549563
case _ => throw new FatalError("symbol " + tree.symbol + " has bad type: " + tree.symbol.info);//debug
550564
}
551565

@@ -561,16 +575,16 @@ trait Contexts { self: Analyzer =>
561575
var renamed = false
562576
var selectors = tree.selectors
563577
while (selectors != Nil && result == NoSymbol) {
564-
if (selectors.head.name != nme.WILDCARD)
565-
notifyImport(name, qual.tpe, selectors.head.name, selectors.head.rename)
578+
// if (selectors.head.name != nme.WILDCARD) // used to be for IDE
579+
// notifyImport(name, qual.tpe, selectors.head.name, selectors.head.rename)
566580

567581
if (selectors.head.rename == name.toTermName)
568-
result = qual.tpe.member(
582+
result = qual.tpe.nonLocalMember( // new to address #2733: consider only non-local members for imports
569583
if (name.isTypeName) selectors.head.name.toTypeName else selectors.head.name)
570584
else if (selectors.head.name == name.toTermName)
571585
renamed = true
572586
else if (selectors.head.name == nme.WILDCARD && !renamed)
573-
result = qual.tpe.member(name)
587+
result = qual.tpe.nonLocalMember(name)
574588
selectors = selectors.tail
575589
}
576590
result

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,8 +1188,17 @@ trait Namers { self: Analyzer =>
11881188
def checkSelectors(selectors: List[ImportSelector]): Unit = selectors match {
11891189
case ImportSelector(from, _, to, _) :: rest =>
11901190
if (from != nme.WILDCARD && base != ErrorType) {
1191-
if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol)
1191+
if (base.member(from) == NoSymbol &&
1192+
base.member(from.toTypeName) == NoSymbol)
11921193
context.error(tree.pos, from.decode + " is not a member of " + expr);
1194+
/* The previous test should be:
1195+
if (base.nonLocalMember(from) == NoSymbol &&
1196+
base.nonLocalMember(from.toTypeName) == NoSymbol)
1197+
context.error(tree.pos, from.decode + " is not a member of " + expr);
1198+
1199+
* but this breaks the jvm/interpreter.scala test, because
1200+
* it seems it imports a local member of a $iw object
1201+
*/
11931202
if (checkNotRedundant(tree.pos, from, to))
11941203
checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName)
11951204
}

0 commit comments

Comments
 (0)