简体   繁体   中英

What does “parameterized overloaded implicit methods are not visible as view bounds” compiler warning mean?

I declared two utility methods as implicit

class MyClass { ... }
object MyClass {
   implicit def finish: MyClass[Any,Nothing,Unit] = finish(());
   implicit def finish[R](result: R): MyClass[Any,Nothing,R] = ...
}

and I'm getting compiler warnings:

parameterized overloaded implicit methods are not visible as view bounds

What does this warning mean?

Here "parameterized" should really be "type parameterized". Or in other wods, the warning says that because you have defined an implicit conversion that is both overloaded (there are other methods of the same name) and generic , then the method cannot actually be used as an implicit view, although it can be used to implicitly convert a mere value. I'll try to illustrate the difference with an example:

class MyClass
object MyClass {
   implicit def finish: MyClass = null
   implicit def finish[R](result: R): MyClass = null
}

val a: Int = 123
val b: MyClass = a // Compiles fine: implicit conversion properly applied

def foo[R<%MyClass]( r: R ) {}
foo( 123 ) // Error: No implicit view available from Int => Test.MyClass

In the above code snippet, a (of type Int ) is implicitly converted to MyClass , so the implicit conversion works as expected.

However, the interesting part is with the foo method. It is declared with a view bound to MyClass . In other words, you should be able to pass to foo any value that is implicitly convertible to MyClass . But here it fails to compile. This is this error that the compiler was warning you about. And sure enough, if you comment out the first overload of finish (the one that does not take a type parameter), or rename a version so that they are not overloads (say you rename one of them to finish2 ), then the compile error goes away.

If you are wondering what is so different between the first case (direct implicit conversion) and the second one (call to method with a view bound) that would allow one to compile fine but not the other, the key point is that a view bound requires to pass a an implicit function value.

Indeed,

def foo[R<%MyClass]( r: R )

is the same as

def foo[R]( r: R )( implicit conv: R => MyClass)

So when calling foo , the compiler not only needs to find the appropriate implicit conversion, but also to promote the implicit conversion method (the second finish overload) to a function instance, and pass it implicitly to foo .

I believe that this is this promotion that the compiler (for some reason) does not know how to do in the case of type parameterized and overloaded methods. This is pure speculation but I am pretty sure that this is just an implementation limitation: this would very much be doable, but it would introduce enough implementation problems that it was not deemed important enough (after all you can fix it by just renaming the implicit conversion method).

As a side note, the warning is not emitted (by default) in scala 2.10 (it was deemed too noisy, with the surge of type class usage in scala), but the real problem remains, and the call to foo still fails to compile.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM