Skip to content

Commit aeb6a9f

Browse files
committed
Simplify combineEligibles logic
1 parent 0908c3a commit aeb6a9f

File tree

3 files changed

+29
-34
lines changed

3 files changed

+29
-34
lines changed

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,11 @@ class PlainPrinter(_ctx: Context) extends Printer {
642642
else s"(no source file, offset = ${pos.span.point})"
643643

644644
def toText(cand: Candidate): Text =
645-
"Candidate(" ~ toText(cand.ref) ~ ", " ~ Str("kind=" + cand.kind) ~ ", " ~ Str("lvl=" + cand.level) ~ ")"
645+
"Cand("
646+
~ toTextRef(cand.ref)
647+
~ (if cand.isConversion then " conv" else "")
648+
~ (if cand.isExtension then " ext" else "")
649+
~ Str(" L" + cand.level) ~ ")"
646650

647651
def toText(result: SearchResult): Text = result match {
648652
case result: SearchSuccess =>

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import ProtoTypes._
2323
import ErrorReporting._
2424
import Inferencing.{fullyDefinedType, isFullyDefined}
2525
import Scopes.newScope
26+
import Typer.BindingPrec, BindingPrec.*
2627
import transform.TypeUtils._
2728
import Hashable._
2829
import 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")

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ object Typer {
6565
case NothingBound, PackageClause, WildImport, NamedImport, Inheritance, Definition
6666

6767
def isImportPrec = this == NamedImport || this == WildImport
68+
69+
/** special cases: definitions beat imports, and named imports beat
70+
* wildcard imports, provided both are in contexts with same scope */
71+
def beats(prevPrec: BindingPrec): Boolean =
72+
this == Definition || this == NamedImport && prevPrec == WildImport
6873
}
6974

7075
/** Assert tree has a position, unless it is empty or a typed splice */
@@ -226,9 +231,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
226231
def checkNewOrShadowed(found: Type, newPrec: BindingPrec, scala2pkg: Boolean = false)(using Context): Type =
227232
if !previous.exists || TypeComparer.isSameRef(previous, found) then
228233
found
229-
else if (prevCtx.scope eq ctx.scope)
230-
&& (newPrec == Definition || newPrec == NamedImport && prevPrec == WildImport)
231-
then
234+
else if (prevCtx.scope eq ctx.scope) && newPrec.beats(prevPrec) then
232235
// special cases: definitions beat imports, and named imports beat
233236
// wildcard imports, provided both are in contexts with same scope
234237
found

0 commit comments

Comments
 (0)