Samar Samar - 1 month ago 5x
Scala Question

error messages on implicit conversion to value classes

Define a method which accepts types: List[_ <: AnyVal]

def foo(x : List[_ <: AnyVal]) = x

Try to use an AnyRef:

foo(List(new Test))

error: type mismatch;
found : Test
required: AnyVal
Note that implicit conversions are not applicable because they are ambiguous:
both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
are possible conversion functions from Test to AnyVal

Question 1: In the warning message, why does the compiler ignore the other two "generic to AnyVal" implicit conversions defined in Predef.scala?

final implicit class StringFormat[A] extends AnyVal
final implicit class any2stringadd[A] extends AnyVal

Removing the previous ambiguity and forcing compiler to use the ArrowAssoc implicit conversion:

foo(List(new Test -> 1))

error: the result type of an implicit conversion must be more specific than AnyVal

Question 2: What is this error message implying? Its confusing. The method
def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y)
in the ArrowAssoc class returns a Tuple2 which is of AnyRef type. So, a more useful error message could have been
found Tuple2 required AnyVal


To answer your second question first. Try this:

class Temp

implicit class Arrow[T](a:T) extends Temp{
  def -->[B](b:B) = (a,b)
def foo(x : List[_ <: Temp]) = x

scala>     foo(List(1 --> 2))
res0: List[Temp] = List(Arrow@2e17a321)

This works as expected. It is not complaining because it was searching for Temp and not Tuple2. Now introduce ambiguity:

implicit class OtherTemp[T](a:T) extends Temp{}
foo(List(1 --> 2)) //compile error

It fails complaining collisions. So to answer your question on why it didn't show AnyRef is because:

Remember ArrowAssoc is being called to get AnyVal representation. With ->, it has a Tuple2 and is trying to retrieve a AnyVal. And because it is unable to retrieve AnyVal, it marks it as error as failure on inability to convert to AnyVal. Its true identity is irrelevant.

For first question: In my understanding, implicits go as first search basis. So once it finds two and there is ambiguity, it quits complaining. May be this is why it doesn't try with StringFormat etc. This can be confirmed on repl by re-ordering implicit order

implicit class OtherTemp2[T](a:T) extends Temp{
implicit class OtherTemp[T](a:T) extends Temp{


Compiler complains as Arrow and OtherTemp2 as collisions. If you re-order and run repl again, it complains based on which implicit was found first. But I cant find an official source which confirms this.