Closed
Description
This will go away once the SIP'd divergence rules are implemented, but leaving this for posterity ...
Given,
object Test {
trait Foo[T, U]
object Foo {
implicit def diverge[T](implicit ev: Foo[T, T]): Foo[T, T] = ???
implicit def foo[T, U]: Foo[T, U] = ???
}
implicitly[Foo[Int, Int]]
}
With the default -Xmin-implicit-search-depth
of 5 the implicitly
compiles as,
/* inlined from dotty.DottyPredef$ */
{
val ev: Test4.Foo[Int, Int] =
Test.Foo.diverge[Int](
Test.Foo.diverge[Int](
Test.Foo.diverge[Int](
Test.Foo.diverge[Int](
Test.Foo.diverge[Int](Test4.Foo.foo[Int, Int])
)
)
)
)
ev
}
With -Xmin-implicit-search-depth
set to 2 it compiles as,
/* inlined from dotty.DottyPredef$ */
{
val ev: Test4.Foo[Int, Int] =
Test.Foo.diverge[Int](
Test.Foo.diverge[Int](Test4.Foo.foo[Int, Int])
)
ev
}
ie. each increment in the value adds an additional call of the diverging implicit before we fail back to the convergent one. We get the expected result only if the parameter is set to 0.
Clearly the entire divergent path should be discarded. It remains to be seen if it's possible to reliably unwind a divergent path or if it would be better to abort the entire search and retry with unconditional divergence checking.