Why does an inapplicable implicit conversion introduce ambiguity?

The setup for this example (Scala 2.10.3):

trait S[A] trait T[A] implicit class X[A : S](a: A) { def foo() { } } implicit class Y[A : T](a: A) { def foo() { } } implicit object I extends S[String] 

This compiles:

 new X("").foo() 

It does not mean:

 new Y("").foo() 

because there is no implicit T[String] .

 could not find implicit value for evidence parameter of type T[String] new Y("").foo() ^ 

Therefore, I would suggest that scalac can uniquely apply an implicit conversion from String to X :

 "".foo() 

But instead we get:

 type mismatch; found : String("") required: ?{def foo: ?} Note that implicit conversions are not applicable because they are ambiguous: both method X of type [A](a: A)(implicit evidence$1: S[A])X[A] and method Y of type [A](a: A)(implicit evidence$1: T[A])Y[A] are possible conversion functions from String("") to ?{def foo: ?} "".foo() ^ 

Is it intentional? Is the skalak not suggesting whether each transformation will really work when it lists candidates?

+6
source share
1 answer

My non-academic view is that the implied design is not intended to work every time, it seems that it should work. I think this is a good idea, otherwise you could easily get into implicit hell. You can expand your example by adding more levels of implicit conversions. It would be hard to say which function is actually called just by looking at the code. There are clearly defined rules, but I just remember that if it is not obvious from the code what is happening, it does not work.

I would say that your code violates the Once-in-Time Rule, which leads to a violation of the Rule that is not related to ambiguity . A : S is just syntactic sugar and can be rewritten to:

 implicit class X[A](a: A)(implicit e: S[A]) { def foo() { } } implicit class Y[A](a: A)(implicit e: T[A]) { def foo() { } } 

Without permission of the "second" implicit level (argument of method e ), both classes X and Y look the same with the compiler and therefore ambiguous. As the linked document says: “ For common sense, the compiler does not insert further implicit conversions when it is already in the middle of trying to use another implicit.

+4
source

All Articles