Implicit ExecutionContext Priority in Scala 2.12

In Scala 2.12, importing a global execution context and then having another implicit execution context defined in scope results in an ambiguous implicit, whereas in 2.11 it works just fine.

 import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global class A(implicit ec: ExecutionContext) { x = implicitly[ExecutionContext] } 

The compiler gives an error:

 error: ambiguous implicit values: both lazy value global in object Implicits of type => scala.concurrent.ExecutionContext and value ec in class A of type scala.concurrent.ExecutionContext match expected type scala.concurrent.ExecutionContext val x = implicitly[ExecutionContext] ^ 

What is the reason for this and how to get around it in code?

+6
source share
1 answer

The specification considers overload resolution as an ambiguity in the selection of class members. But implicit resolution uses static overload resolution to choose between links that are not members.

Perhaps the following misinterpretation of spec, since zzz defined in a class derived from X , like yyy :

 $ 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] } ^ 

You should currently rely on naming to make the shadow hidden from the 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> 
+2
source

Source: https://habr.com/ru/post/1012065/


All Articles