The spec treats overload resolution as the disambiguation of a selection of members of a class. But implicit resolution uses static overload resolution to choose between references which are not members.
Arguably, the following is a misinterpretation of the spec, since zzz
is defined in a class derived from X
much as yyy
is:
$ scala
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.
scala> import concurrent._, ExecutionContext.global
import concurrent._
import ExecutionContext.global
scala> trait X { implicit val xxx: ExecutionContext = global }
defined trait X
scala> class Y extends X { implicit val yyy: ExecutionContext = global ; def f = implicitly[ExecutionContext] }
defined class Y
scala> class Z extends X { def f(implicit zzz: ExecutionContext) = implicitly[ExecutionContext] }
<console>:16: error: ambiguous implicit values:
both value xxx in trait X of type => scala.concurrent.ExecutionContext
and value zzz of type scala.concurrent.ExecutionContext
match expected type scala.concurrent.ExecutionContext
class Z extends X { def f(implicit zzz: ExecutionContext) = implicitly[ExecutionContext] }
^
Currently, you must rely on naming to shadow the implicit from enclosing scope:
scala> class Z extends X { def f(implicit xxx: ExecutionContext) = implicitly[ExecutionContext] }
defined class Z
Or,
scala> :pa
// Entering paste mode (ctrl-D to finish)
package object p { import concurrent._ ; implicit val xxx: ExecutionContext = ExecutionContext.global }
package p { import concurrent._ ;
class P { def f(implicit xxx: ExecutionContext) = implicitly[ExecutionContext]
def g = implicitly[ExecutionContext] }
}
// Exiting paste mode, now interpreting.
scala>