@@ -23,6 +23,7 @@ import ProtoTypes._
23
23
import ErrorReporting ._
24
24
import Inferencing .{fullyDefinedType , isFullyDefined }
25
25
import Scopes .newScope
26
+ import Typer .BindingPrec , BindingPrec .*
26
27
import transform .TypeUtils ._
27
28
import Hashable ._
28
29
import util .{EqHashMap , Stats }
@@ -49,7 +50,7 @@ object Implicits:
49
50
}
50
51
51
52
/** Both search candidates and successes are references with a specific nesting level. */
52
- sealed trait RefAndLevel {
53
+ sealed trait RefAndLevel extends Showable {
53
54
def ref : TermRef
54
55
def level : Int
55
56
}
@@ -328,41 +329,28 @@ object Implicits:
328
329
(this eq finalImplicits) || (outerImplicits eqn finalImplicits)
329
330
}
330
331
332
+ def bindingPrec : BindingPrec =
333
+ if isImport then if ctx.importInfo.uncheckedNN.isWildcardImport then WildImport else NamedImport else Definition
334
+
331
335
private def combineEligibles (ownEligible : List [Candidate ], outerEligible : List [Candidate ]): List [Candidate ] =
332
336
if ownEligible.isEmpty then outerEligible
333
337
else if outerEligible.isEmpty then ownEligible
334
338
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)* )
340
340
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
364
351
else
365
- ownEligible ::: filter(outerEligible, ownEligible)
352
+ ownEligible ::: outerEligible.filterConserve: cand =>
353
+ ! ownNames.contains(cand.ref.implicitName)
366
354
367
355
def uncachedEligible (tp : Type )(using Context ): List [Candidate ] =
368
356
Stats .record(" uncached eligible" )
0 commit comments