Open scabug opened 11 years ago
Imported From: https://issues.scala-lang.org/browse/SI-7697?orig=1 Reporter: @paulp Affected Versions: 2.10.4, 2.11.5
@retronym said:
The terminology is confusing here. "Ambiguous implicits" describes competing, applicable implicits which score equally on the specificity test. Here, we have have an ambiguous binding. This is really an "invalid implicit", as diagnosed by -Xlog-implicits
qscalac -Xlog-implicits sandbox/test1.scala
sandbox/test1.scala:9: <string2int: error> is not a valid implicit value for String("abc") => Int because:
reference to string2int is ambiguous;
it is imported twice in the same scope by
import o2._
and import o1._
val x: Int = "abc"
^
sandbox/test1.scala:9: error: type mismatch;
found : String("abc")
required: Int
val x: Int = "abc"
^
one error found
Secondarily, it would be nice if this situation were recognized as the non-conflict which it is: the "conflicting" implicits are prefix-insensitive and the identical method implementation.
Given separate compilation, we can only base our decision on the type signature, not on the body of the method.
We should figure out how to emit the useful output of -Xlog-implicits
when and where it is needed. I've never been able to figure out the right balance here, though.
@paulp said: I don't understand the relevance of separate compilation. I didn't mean go decompiling the bytecode to look at the the method, I meant they are literally the identical method, in the same sense that "Fido the dog" and "Fido the dog" are known to be equal because there is only one Fido the dog. They each have their own synthetic forwarder and each one exists for no reason but delivering Fido the dog.
@retronym said:
They could, however, predicate some logic on the identity of Impy.this
.
@paulp said: Shoot. You got me.
@paulp said: I don't know if someone else ever reported this - guessing not - I'll just throw it in here as the closest thing to an applicable ticket. Fair warning, this is probably a slide in every talk I give until I die or it is changed, whichever comes first.
https://gist.github.com/paulp/36b67d27400a9f3be96a
class Bippy(override val toString: String)
trait A { implicit def lowPriority: Bippy = new Bippy("A") }
object B extends A { implicit def highPriority: Bippy = new Bippy("B") }
object C { implicit def highPriority: Bippy = new Bippy("C") }
object Test {
def main(args: Array[String]): Unit = {
import B._, C._
println( implicitly[Bippy] ) // Prints: A
}
}
@retronym said:
Yep, -Xlog-implicts
tells you about that one, too.
qscalac -Xlog-implicits sandbox/test1.scala
sandbox/test1.scala:10: <highPriority: error> is not a valid implicit value for Bippy because:
reference to highPriority is ambiguous;
it is imported twice in the same scope by
import C._
and import B._
println( implicitly[Bippy] ) // Prints: A
^
But one man's trash is another man's treasure when it comes to these diagnostics. I don't think they are in a state to turn on by default.
@paulp said:
It's good of -Xlog-implicits to note the ambiguity, but I might once have naively thought it would also fail the compile. It's quite interesting that it can echo a message including "
The appended error message is seen under -Ylog:typer, but under normal compilation scalac offers nothing.
Secondarily, it would be nice if this situation were recognized as the non-conflict which it is: the "conflicting" implicits are prefix-insensitive and the identical method implementation. This situation arises very easily when mixing implicits into package objects and trying to evolve codebases.
But at the very least how about we give people a hint what happened.