Skip to content

Commit 859d30b

Browse files
committed
Find all implicits first
1 parent 82d69a7 commit 859d30b

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,7 +2555,7 @@ class MissingImplicitArgument(
25552555
where: String,
25562556
paramSymWithMethodCallTree: Option[(Symbol, tpd.Tree)] = None,
25572557
ignoredInstanceNormalImport: => Option[SearchSuccess],
2558-
ignoredConversions: => Iterable[TermRef]
2558+
ignoredConversions: => Iterable[(TermRef, Iterable[TermRef])]
25592559
)(using Context) extends TypeMsg(MissingImplicitArgumentID), ShowMatchTrace(pt):
25602560

25612561
arg.tpe match
@@ -2744,12 +2744,18 @@ class MissingImplicitArgument(
27442744
// show all available additional info
27452745
def hiddenImplicitNote(s: SearchSuccess) =
27462746
i"\n\nNote: ${s.ref.symbol.showLocated} was not considered because it was not imported with `import given`."
2747-
def noChainConversionsNote(ignoredConversions: Iterable[TermRef]): Option[String] =
2747+
def showImplicitAndConversions(imp: TermRef, convs: Iterable[TermRef]) =
2748+
i"\n- ${imp.symbol.showDcl}${convs.map(c => "\n - " + c.symbol.showDcl).mkString}"
2749+
def noChainConversionsNote(ignoredConversions: Iterable[(TermRef, Iterable[TermRef])]): Option[String] = {
2750+
val convsFormatted = ignoredConversions.map{ (imp, convs) =>
2751+
i"\n- ${imp.symbol.showDcl}${convs.map(c => "\n - " + c.symbol.showDcl).mkString}"
2752+
}.mkString
27482753
Option.when(ignoredConversions.nonEmpty)(
27492754
i"\n\nNote: implicit conversions are not automatically applied to arguments of using clauses. " +
27502755
i"You will have to pass the argument explicitly.\n" +
2751-
i"The following conversions in scope result in ${pt.show}: ${ignoredConversions.map(g => s"\n - ${g.symbol.showDcl}").mkString}"
2756+
i"The following conversions in scope result in ${pt.show}: $convsFormatted"
27522757
)
2758+
}
27532759
super.msgPostscript
27542760
++ ignoredInstanceNormalImport.map(hiddenImplicitNote)
27552761
.orElse(noChainConversionsNote(ignoredConversions))

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -923,11 +923,21 @@ trait Implicits:
923923
// example where searching for a nested type causes an infinite loop.
924924
None
925925

926+
def allImplicits(currImplicits: ContextualImplicits): List[ImplicitRef] =
927+
if currImplicits.outerImplicits == null then currImplicits.refs
928+
else currImplicits.refs ::: allImplicits(currImplicits.outerImplicits)
929+
926930
def ignoredConversions = arg.tpe match
927931
case fail: SearchFailureType =>
932+
// Get every implicit in scope and find Conversions for each
928933
if (fail.expectedType eq pt) || isFullyDefined(fail.expectedType, ForceDegree.none) then
929-
ctx.implicits.eligible(ViewProto(WildcardType, wildApprox(fail.expectedType)))
930-
.collect { case c if c.isConversion => c.ref }
934+
// todo filter out implicit conversions
935+
allImplicits(ctx.implicits).map { imp =>
936+
// todo imp.underlyingRef.underlying does not work for implicit functions or givens
937+
// with type or implicit parameters
938+
val convs = ctx.implicits.eligible(ViewProto(imp.underlyingRef.underlying, wildApprox(fail.expectedType)))
939+
(imp.underlyingRef, convs.map(_.ref))
940+
}.filter(_._2.nonEmpty)
931941
else
932942
Nil
933943

tests/neg/i16453.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import scala.language.implicitConversions
22

3+
trait Foo { type T }
4+
35
// Scala 3 style conversion
4-
given [T]: Conversion[T, Option[T]] = ???
6+
// given [T]: Conversion[T, Option[T]] = ???
7+
given [F <: Foo](using f: F): Conversion[f.T, Option[f.T]] = ???
58
// Scala 2 style conversion
69
implicit def toOption[T](t: T): Option[T] = Option(t)
710

811
// This one is irrelevant, shouldn't be included in error message
912
given irrelevant: Conversion[Int, Option[Long]] = ???
1013

1114
def test() = {
12-
given foo: Int = 0
15+
given foo: Foo with
16+
type T = Int
17+
given bar: Int = 0
1318

1419
summon[Option[Int]] // error
1520
implicitly[Option[Int]] // error

0 commit comments

Comments
 (0)