You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consider the following program:
```scala
class A
class B extends A
class C extends A
given A = A()
given B = B()
given C = C()
def f(using a: A, b: B, c: C) =
println(a.getClass)
println(b.getClass)
println(c.getClass)
@main def Test = f
```
With the current rules, this would fail with an ambiguity error between B and C when
trying to synthesize the A parameter. This is a problem without an easy remedy.
We can fix this problem by flipping the priority for implicit arguments. Instead of
requiring an argument to be most _specific_, we now require it to be most _general_
while still conforming to the formal parameter.
There are three justifications for this change, which at first glance seems quite drastic:
- It gives us a natural way to deal with inheritance triangles like the one in the code above.
Such triangles are quite common.
- Intuitively, we want to get the closest possible match between required formal parameter type and
synthetisized argument. The "most general" rule provides that.
- We already do a crucial part of this. Namely, with current rules we interpolate all
type variables in an implicit argument downwards, no matter what their variance is.
This makes no sense in theory, but solves hairy problems with contravariant typeclasses
like `Comparable`. Instead of this hack, we now do something more principled, by
flipping the direction everywhere, preferring general over specific, instead of just
flipping contravariant type parameters.
# Conflicts:
# compiler/src/dotty/tools/dotc/typer/Implicits.scala
0 commit comments