Reputation: 1798
% scala
Welcome to Scala 2.12.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> trait Op[-Y, -Z, +A, +B] {
| def apply(other: (Y, Z)): (A, B)
| }
defined trait Op
scala> implicit class RichTuple2[+A, +B](t: (A, B)) {
| def ~~~(other: Int): (A, B) = ???
| def ~~~[RA, RB](other: Op[A, B, RA, RB]): (RA, RB) = other.apply(t)
| }
defined class RichTuple2
scala> def swap[A, B] = new Op[A, B, B, A] {
| override def apply(other: (A, B)) = (other._2, other._1)
| }
swap: [A, B]=> Op[A,B,B,A]
scala> (1, "foo") ~~~ swap
<console>:14: error: overloaded method value ~~~ with alternatives:
[RA, RB](other: Op[Int,String,RA,RB])(RA, RB) <and>
(other: Int)(Int, String)
cannot be applied to (Op[Nothing,Nothing,Nothing,Nothing])
(1, "foo") ~~~ swap
If I remove the first ~~~(other: Int)
method, then it works:
scala> trait Op[-Y, -Z, +A, +B] {
| def apply(other: (Y, Z)): (A, B)
| }
defined trait Op
scala> implicit class RichTuple2[+A, +B](t: (A, B)) {
| def ~~~[RA, RB](other: Op[A, B, RA, RB]): (RA, RB) = other.apply(t)
| }
defined class RichTuple2
scala> def swap[A, B] = new Op[A, B, B, A] {
| override def apply(other: (A, B)) = (other._2, other._1)
| }
swap: [A, B]=> Op[A,B,B,A]
scala> (1, "foo") ~~~ swap
res0: (String, Int) = (foo,1)
The question is why type inference and method selection fails in this case? The method ~~~(other: Int)
takes a parameter that isn't at all related to the type of swap
(with is an Op
type). And is anyone aware of a workaround?
Upvotes: 0
Views: 52
Reputation: 810
scalac sometimes has trouble finding the right implicits or inferring the right types when one mixes implicits with overloading.
There are several jira tickets on this topic, and this particular one: SI-9523, appears to be the same problem as the one in your question.
In your case scalac is unable to infer the type arguments for swap
when ~~~
is overloaded, so annotating it with swap[Int, String]
should work.
Overloading is generally discouraged in Scala (see Why "avoid method overloading"?) and (http://www.wartremover.org/doc/warts.html), so the best solution is to avoid overloading.
Upvotes: 1