Skip to content

Commit 8a60a20

Browse files
committed
Make hasEq look in implicit scope even if an eqAny is visible
1 parent 8b0aca2 commit 8a60a20

File tree

1 file changed

+19
-11
lines changed

1 file changed

+19
-11
lines changed

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ trait Implicits { self: Typer =>
706706
}
707707

708708
/** An implicit search; parameters as in `inferImplicit` */
709-
class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Position)(implicit ctx: Context) {
709+
class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Position, contextual: Boolean = true)(implicit ctx: Context) {
710710

711711
private def nestedContext = ctx.fresh.setMode(ctx.mode &~ Mode.ImplicitsEnabled)
712712

@@ -743,7 +743,7 @@ trait Implicits { self: Typer =>
743743
def typedImplicit(cand: Candidate)(implicit ctx: Context): SearchResult = track("typedImplicit") { ctx.traceIndented(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) {
744744
assert(constr eq ctx.typerState.constraint)
745745
val ref = cand.ref
746-
var generated: Tree = tpd.ref(ref).withPos(pos.startPos)
746+
var generated: Tree = tpd.ref(ref).withPos(pos)
747747
if (!argument.isEmpty)
748748
generated = typedUnadapted(
749749
untpd.Apply(untpd.TypedSplice(generated), untpd.TypedSplice(argument) :: Nil),
@@ -759,13 +759,19 @@ trait Implicits { self: Typer =>
759759
case _ => false
760760
}
761761
}
762-
// Does there exist an implicit value of type `Eq[tp, tp]`?
763-
def hasEq(tp: Type): Boolean =
764-
new ImplicitSearch(defn.EqType.appliedTo(tp, tp), EmptyTree, pos).bestImplicit match {
765-
case result: SearchSuccess => result.ref.symbol != defn.Predef_eqAny
766-
case result: AmbiguousImplicits => true
767-
case _ => false
768-
}
762+
// Does there exist an implicit value of type `Eq[tp, tp]`
763+
// which is different from `eqAny`?
764+
def hasEq(tp: Type): Boolean = {
765+
def search(contextual: Boolean): Boolean =
766+
new ImplicitSearch(defn.EqType.appliedTo(tp, tp), EmptyTree, pos, contextual).bestImplicit match {
767+
case result: SearchSuccess =>
768+
result.ref.symbol != defn.Predef_eqAny ||
769+
contextual && search(contextual = false)
770+
case result: AmbiguousImplicits => true
771+
case _ => false
772+
}
773+
search(contextual = true)
774+
}
769775

770776
def validEqAnyArgs(tp1: Type, tp2: Type) = {
771777
List(tp1, tp2).foreach(fullyDefinedType(_, "eqAny argument", pos))
@@ -873,11 +879,13 @@ trait Implicits { self: Typer =>
873879

874880
/** Find a unique best implicit reference */
875881
def bestImplicit: SearchResult = {
876-
searchImplicits(ctx.implicits.eligible(wildProto), contextual = true) match {
882+
searchImplicits(ctx.implicits.eligible(wildProto), contextual) match {
877883
case result: SearchSuccess => result
878884
case result: AmbiguousImplicits => result
879885
case result: SearchFailure =>
880-
searchImplicits(implicitScope(wildProto).eligible, contextual = false)
886+
if (contextual)
887+
searchImplicits(implicitScope(wildProto).eligible, contextual = false)
888+
else result
881889
}
882890
}
883891

0 commit comments

Comments
 (0)