@@ -23,6 +23,7 @@ import ProtoTypes._
2323import ErrorReporting ._
2424import Inferencing .{fullyDefinedType , isFullyDefined }
2525import Scopes .newScope
26+ import Typer .BindingPrec , BindingPrec .*
2627import transform .TypeUtils ._
2728import Hashable ._
2829import util .{EqHashMap , Stats }
@@ -49,7 +50,7 @@ object Implicits:
4950 }
5051
5152 /** Both search candidates and successes are references with a specific nesting level. */
52- sealed trait RefAndLevel {
53+ sealed trait RefAndLevel extends Showable {
5354 def ref : TermRef
5455 def level : Int
5556 }
@@ -328,41 +329,28 @@ object Implicits:
328329 (this eq finalImplicits) || (outerImplicits eqn finalImplicits)
329330 }
330331
332+ def bindingPrec : BindingPrec =
333+ if isImport then if ctx.importInfo.uncheckedNN.isWildcardImport then WildImport else NamedImport else Definition
334+
331335 private def combineEligibles (ownEligible : List [Candidate ], outerEligible : List [Candidate ]): List [Candidate ] =
332336 if ownEligible.isEmpty then outerEligible
333337 else if outerEligible.isEmpty then ownEligible
334338 else
335- def filter (xs : List [Candidate ], remove : List [Candidate ]) =
336- // Drop candidates that are shadowed by candidates in "remove"
337- val shadowed = remove.map(_.ref.implicitName).toSet
338- xs.filterConserve(cand => ! shadowed.contains(cand.ref.implicitName))
339-
339+ val ownNames = mutable.Set (ownEligible.map(_.ref.implicitName)* )
340340 val outer = outerImplicits.uncheckedNN
341- def isWildcardImport (using Context ) = ctx.importInfo.nn.isWildcardImport
342- def preferDefinitions = isImport && ! outer.isImport
343- def preferNamedImport = isWildcardImport && ! isWildcardImport(using outer.irefCtx)
344-
345- if ! migrateTo3(using irefCtx) && level == outer.level && (preferDefinitions || preferNamedImport) then
346- // special cases: definitions beat imports, and named imports beat
347- // wildcard imports, provided both are in contexts with same scope
348-
349- // Using only the outer candidates at the same level as us,
350- // remove from our own eligibles any shadowed candidate.
351- // This removes locally imported candidates from shadowing local definitions, (foo's in i18316)
352- // but without a remotely imported candidate removing a more locally imported candidates (mkFoo's in i18183)
353- val ownEligible1 = filter(ownEligible, outerEligible.filter(_.level == level))
354-
355- // Remove, from the outer eligibles, any candidate shadowed by one of our own candidates,
356- // provided that the outer eligibles aren't at the same level (so actually shadows).
357- // This complements the filtering of our own eligible candidates, by removing candidates in the outer candidates
358- // that are low-level priority and shadowed by our candidates. E.g. the outer import Imp.mkFoo in i18183.
359- val shadowed = ownEligible.map(_.ref.implicitName).toSet
360- val outerEligible1 =
361- outerEligible.filterConserve(cand => cand.level == level || ! shadowed.contains(cand.ref.implicitName))
362-
363- ownEligible1 ::: outerEligible1
341+ if ! migrateTo3(using irefCtx) && level == outer.level && outer.bindingPrec.beats(bindingPrec) then
342+ val keptOuters = outerEligible.filterConserve: cand =>
343+ if ownNames.contains(cand.ref.implicitName) then
344+ val keepOuter = cand.level == level
345+ if keepOuter then ownNames -= cand.ref.implicitName
346+ keepOuter
347+ else true
348+ val keptOwn = ownEligible.filterConserve: cand =>
349+ ownNames.contains(cand.ref.implicitName)
350+ keptOwn ::: keptOuters
364351 else
365- ownEligible ::: filter(outerEligible, ownEligible)
352+ ownEligible ::: outerEligible.filterConserve: cand =>
353+ ! ownNames.contains(cand.ref.implicitName)
366354
367355 def uncachedEligible (tp : Type )(using Context ): List [Candidate ] =
368356 Stats .record(" uncached eligible" )
0 commit comments