-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix compilation under Scala 3.6 new givens prioritization scheme #238
Conversation
@@ -63,7 +63,7 @@ class InstancesTests: | |||
|
|||
@Test | |||
def mapKforSingle: Unit = | |||
val inst = summon[K0.Instances[TypeClass, Single[Int]]] | |||
val inst = summon[K0.ProductInstances[TypeClass, Single[Int]]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the change required? What's wrong with the original implementation?
I think if this test is broken, it would be broken for users too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It all comes to how the implicit are resolved, in short let's start with a description from PR:
Instead of requiring an argument to be most specific, we now require it to be most general while still conforming to the formal parameter.
...
Intuitively, we want to get the closest possible match between required formal parameter type and synthetisized argument. The "most general" rule provides that.
In shapeless there is defined a given method creating both K0.Instances
and K0.ProductInstances
Under the old implicit rule, we were getting granted the most specific available type, in our case that's ProductInstances, so even though there exists inline given mkInstances[F[_], T](using gen: Generic[T]): Instances[F, T]
it would never be picked, instead, the compiler would always choose inline given mkProductInstances[F[_], T](using gen: ProductGeneric[T]): ProductInstances[F, T]
Now, since 3.6 when asked for K0.Instances
and when having an access to instance of this type directly, compiler would choose it instead of using it's more specific subtype.
Because of this single change, the result of the summon has changed. We no longer have access to ProductInstances
but to the Instances
. Now in the next few lines when we try to use foldLeft
on transformed values, we get to the clue of the problem - there is no instance of Foldable
instance defined for K0.Instances
so the compilation files with type mismatch.
Overall it's very similar to the case from the PR's snippert:
class A
class B extends A
class C extends A
@main def Test =
given A = A()
given B = B()
def f0(using a: A, b: B) = ()
f0 // evaluates to f(using given B, given B)
given C = C()
def f1(using a: A, b: B, c: C) = ()
f1 // error: ambiguous implicits, compiler cannot choose between given B and given C to use for argument `a`
In the case of shapeless the only difference was that both ProductInstances
and CoproductInstances
could have never been constructed at the same time, which allowed for compilation.
Probably using method similar toK0.mkInstances[?, ?]
after making it transparent inline
but not given
should be a decent workaround instead of using summon[K0.Instances[?, ?]]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, thanks - foldLeft
is missing from Instances
. That's fine.
Applies a patch required after merge of scala/scala3#19300 to one of the tests to make it compile under Scala 3.6 in the Scala 3 Open Community Build. This change is a cherry-pick from a Scala 3 Small / Managed Communty Build run on the fork of this project