"Weird" generic implicit resolution behaviour

In a project I’m working on, I have a project with a given instance looking like this (simplified):

class Test[A, B]

inline given [A, B](using A): Test[A, Test[A, B]] = new Test

This works as intended when summoning something like

given Int = ???
given String = ???

summon[Test[Int, Test[Int, String]]] //OK

But if I change generics:

given Int = ???
given String = ???

summon[Test[Int, Test[String, Int]]] //Ambiguous implicit argument between given_Int and given_String

Since Test[Int, Test[String, Int]] does not match Test[A, Test[A, B]], I would expect the compiler to just ignore the above given and use another/give a “no suitable given found” error.

After doing some tests, it works if I remove the using A:

inline given [A, B]: Test[A, Test[A, B]] = new Test

summon[Test[Int, Test[Int, String]]] //OK
summon[Test[Int, Test[String, Int]]] //Search for another given instance

It seems that the compiler tries to evaluate the using A parameter first using ? since Test[?, Test[?, ?]] matches the type Test[A, Test[A, B]] and ? is a (as far as I know) supertype of Int and String.

I prefer posting here first before opening an issue on Github.
Is this the correct behaviour? If yes, how can I make the compiler just “skip” this given in the second case instead of checking with A = ? and B = ??

1 Like

The error message progressed since 3.1.0 to give even less information about what it tried.

There is a difference in messaging between

def gotten: Test[Int, Test[String, Int]] = given_Test_A_Test
def taken: Test[Int, Test[String, Int]] = summon

where, with the using clause deleted, gotten gives an “even better” message. Probably I expect that message for taken because it says “I found [one thing to try]”, so just pretend I wrote that explicitly.

With the using clause restored, gotten produces a surprisingly long and unhelpful list of suggested imports. taken is just the message for /* missing */summon[A].

It might be a “feature request”, but maybe “if there is one implicit candidate, show messaging after assuming dependent searches succeeded and as if the invocation were explicit.” That might be an addendum to whatever the current error is, if it adds information.

Possibly, at least supply the addendum if I asked for -explain.

2 Likes

I agree this could be a cool feature request but there’s a real limitation of the compiler in this issue.

I think the compiler should consider ambiguous as unmatching the requested type. If all candidates were ambiguous then it should produce the common “ambiguous given”.
Maybe my explenation would be more understandable with a tree representing the implicit search.