diff --git a/_overviews/scala3-migration/incompat-contextual-abstractions.md b/_overviews/scala3-migration/incompat-contextual-abstractions.md index cd43809c28..ba88ed62f0 100644 --- a/_overviews/scala3-migration/incompat-contextual-abstractions.md +++ b/_overviews/scala3-migration/incompat-contextual-abstractions.md @@ -27,25 +27,31 @@ The Scalafix rule named `ExplicitImplicitTypes` in [ohze/scala-rewrites](https:/ Scala 3 does not support implicit conversion from an implicit function value, of the form `implicit val ev: A => B`. -The following piece of code is now invalid: +{% tabs scala-2-implicit_1 %} +{% tab 'Scala 2 Only' %} -```scala +The following piece of code is now invalid in Scala 3: +~~~ scala trait Pretty { val print: String } def pretty[A](a: A)(implicit ev: A => Pretty): String = - a.print // Error: value print is not a member of A -``` + a.print // In Scala 3, Error: value print is not a member of A +~~~ +{% endtab %} +{% endtabs %} The [Scala 3 migration compilation](tooling-migration-mode.html) can warn you about those cases, but it does not try to fix it. Be aware that this incompatibility can produce a runtime incompatibility and break your program. Indeed the compiler can find another implicit conversion from a broader scope, which would eventually cause an undesired behavior at runtime. -This example illustrates the case: +{% tabs shared-implicit_2 %} +{% tab 'Scala 2 and 3' %} -```scala +This example illustrates the case: +~~~ scala trait Pretty { val print: String } @@ -54,13 +60,15 @@ implicit def anyPretty(any: Any): Pretty = new Pretty { val print = "any" } def pretty[A](a: A)(implicit ev: A => Pretty): String = a.print // always print "any" -``` +~~~ +{% endtab %} +{% endtabs %} The resolved conversion depends on the compiler mode: - `-source:3.0-migration`: the compiler performs the `ev` conversion - `-source:3.0`: the compiler cannot perform the `ev` conversion but it can perform the `anyPretty`, which is undesired -One simple fix is to supply the right conversion explicitly: +In Scala 3, one simple fix is to supply the right conversion explicitly: {% highlight diff %} def pretty[A](a: A)(implicit ev: A => Pretty): String = @@ -73,11 +81,15 @@ def pretty[A](a: A)(implicit ev: A => Pretty): String = View bounds have been deprecated for a long time but they are still supported in Scala 2.13. They cannot be compiled with Scala 3 anymore. -```scala +{% tabs scala-2-bounds_1 %} +{% tab 'Scala 2 Only' %} +~~~ scala def foo[A <% Long](a: A): Long = a -``` +~~~ +{% endtab %} +{% endtabs %} -In this example we get: +In this example, in Scala 3, we get this following error message: {% highlight text %} -- Error: src/main/scala/view-bound.scala:2:12 @@ -104,12 +116,16 @@ It is not the case in Scala 3 anymore, and leads to an ambiguous conversion. For instance, in this example: -```scala +{% tabs scala-2-ambiguous_1 %} +{% tab 'Scala 2 Only' %} +~~~ scala implicit def boolFoo(bool: Boolean): Foo = ??? implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ??? true.foo() -``` +~~~ +{% endtab %} +{% endtabs %} The Scala 2.13 compiler chooses the `boolFoo` conversion but the Scala 3 compiler fails to compile. @@ -131,4 +147,4 @@ implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ??? -true.foo() +boolFoo(true).foo() -{% endhighlight %} +{% endhighlight %} \ No newline at end of file