@@ -27,17 +27,17 @@ The Scalafix rule named `ExplicitImplicitTypes` in [ohze/scala-rewrites](https:/
2727
2828Scala 3 does not support implicit conversion from an implicit function value, of the form ` implicit val ev: A => B ` .
2929
30- {% tabs scala-3 -implicit_1 %}
31- {% tab 'Scala 3 Only' %}
30+ {% tabs scala-2 -implicit_1 %}
31+ {% tab 'Scala 2 Only' %}
3232
33- The following piece of code is now invalid:
33+ The following piece of code is now invalid in Scala 3 :
3434~~~ scala
3535trait Pretty {
3636 val print : String
3737}
3838
3939def pretty [A ](a : A )(implicit ev : A => Pretty ): String =
40- a.print // Error: value print is not a member of A
40+ a.print // In Scala 3, Error: value print is not a member of A
4141~~~
4242{% endtab %}
4343{% endtabs %}
@@ -47,8 +47,8 @@ The [Scala 3 migration compilation](tooling-migration-mode.html) can warn you ab
4747Be aware that this incompatibility can produce a runtime incompatibility and break your program.
4848Indeed the compiler can find another implicit conversion from a broader scope, which would eventually cause an undesired behavior at runtime.
4949
50- {% tabs scala-3 -implicit_2 %}
51- {% tab 'Scala 3 Only ' %}
50+ {% tabs shared -implicit_2 %}
51+ {% tab 'Scala 2 and 3 ' %}
5252
5353This example illustrates the case:
5454~~~ scala
@@ -61,69 +61,62 @@ implicit def anyPretty(any: Any): Pretty = new Pretty { val print = "any" }
6161def pretty [A ](a : A )(implicit ev : A => Pretty ): String =
6262 a.print // always print "any"
6363~~~
64+ {% endtab %}
65+ {% endtabs %}
6466
6567The resolved conversion depends on the compiler mode:
6668 - ` -source:3.0-migration ` : the compiler performs the ` ev ` conversion
6769 - ` -source:3.0 ` : the compiler cannot perform the ` ev ` conversion but it can perform the ` anyPretty ` , which is undesired
6870
69- One simple fix is to supply the right conversion explicitly:
71+ In Scala 3, one simple fix is to supply the right conversion explicitly:
7072
71- ~~~ scala
73+ {% highlight diff %}
7274def pretty[ A] (a: A)(implicit ev: A => Pretty): String =
73- ev(a).print
74- ~~~
75- {% endtab %}
76- {% endtabs %}
75+ - a.print
76+ + ev(a).print
77+ {% endhighlight %}
7778
7879## View Bounds
7980
8081View bounds have been deprecated for a long time but they are still supported in Scala 2.13.
8182They cannot be compiled with Scala 3 anymore.
8283
83- {% tabs scala-3 -bounds_1 %}
84- {% tab 'Scala 3 Only' %}
84+ {% tabs scala-2 -bounds_1 %}
85+ {% tab 'Scala 2 Only' %}
8586~~~ scala
8687def foo [A <% Long ](a : A ): Long = a
8788~~~
89+ {% endtab %}
90+ {% endtabs %}
8891
89- In this example we get:
92+ In this example, in Scala 3, we get this following error message :
9093
91- ~~~ text
94+ {% highlight text %}
9295-- Error: src/main/scala/view-bound.scala:2:12
93962 | def foo[ A <% Long] (a: A): Long = a
9497 | ^
9598 | view bounds ` <%' are deprecated, use a context bound ` :' instead
9699~~~
97- {% endtab %}
98- {% endtabs %}
100+ {% endhighlight %}
99101
100102The message suggests to use a context bound instead of a view bound but it would change the signature of the method.
101103It is probably easier and safer to preserve the binary compatibility.
102104To do so the implicit conversion must be declared and called explicitly.
103105
104106Be careful not to fall in the runtime incompatibility described above, in [Implicit Views](#implicit-views).
105107
106- {% tabs runtime_1 class=tabs-scala-version %}
107- {% tab 'Scala 2' for=runtime_1 %}
108- ~~~ scala
109- def foo [A <% Long ](a : A ): Long = a
110- ~~~
111-
112- {% endtab %}
113- {% tab 'Scala 3' for=runtime_1 %}
114- ~~~ scala
115- def foo [A ](a : A )(implicit ev : A => Long ): Long = ev(a)
116- ~~~
117- {% endtab %}
118- {% endtabs %}
108+ {% highlight diff %}
109+ -def foo[A <% Long](a: A): Long = a
110+ +def foo[A](a: A)(implicit ev: A => Long): Long = ev(a)
111+ {% endhighlight %}
119112
120113## Ambiguous Conversion On `A` And `=> A`
121114
122115In Scala 2.13 the implicit conversion on `A` wins over the implicit conversion on `=> A`.
123116It is not the case in Scala 3 anymore, and leads to an ambiguous conversion.
124117
125- {% tabs ambiguous_1 class=tabs- scala-version %}
126- {% tab 'Scala 2' for=ambiguous_1 %}
118+ {% tabs scala-2-ambiguous_1 %}
119+ {% tab 'Scala 2 Only' %}
127120
128121For instance, in this example:
129122~~~ scala
@@ -132,28 +125,27 @@ implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ???
132125
133126true.foo()
134127~~~
128+ {% endtab %}
129+ {% endtabs %}
135130
136131The Scala 2.13 compiler chooses the ` boolFoo ` conversion but the Scala 3 compiler fails to compile.
137132
138- ~~~ text
133+ {% highlight text %}
139134-- Error: src/main/scala/ambiguous-conversion.scala:4:19
1401359 | true.foo()
141136 | ^^^^
142137 |Found: (true : Boolean)
143138 |Required: ?{ foo: ? }
144139 |Note that implicit extension methods cannot be applied because they are ambiguous;
145140 |both method boolFoo in object Foo and method lazyBoolFoo in object Foo provide an extension method ` foo ` on (true : Boolean)
146- ~~~
147- {% endtab %}
148- {% tab 'Scala 3' for=ambiguous_1 %}
141+ {% endhighlight %}
149142
150143A temporary solution is to write the conversion explicitly.
151144
152- ~~~ scala
145+ {% highlight diff %}
153146implicit def boolFoo(bool: Boolean): Foo = ???
154147implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ???
155148
156- boolFoo(true ).foo()
157- ~~~
158- {% endtab %}
159- {% endtabs %}
149+ -true.foo()
150+ +boolFoo(true).foo()
151+ {% endhighlight %}
0 commit comments