`implicit` vs `using` migration

Scala 3 handles using vs implicit in different ways:

trait Dummy
def foo(i: Int)(implicit d: Dummy): String => String = _ * i
def bar(i: Int)(using Dummy): String => String = _ * i

given Dummy = new Dummy {}
foo(5)("test") // Fails with Found: ("test" : String) Required: Dummy
bar(5)("test")

I assume this is by design to ease migration from 2.13.

I suggest the following changes under -source:future -deprecation:

  • Scala 3 code using implicit should emit a deprecation warning.
  • Scala 3 code using 2.13 code (from a library) which still uses implicit should behave as if using was used. Keeping with the example above: assume the method foo was defined in the 2.13 library, the call foo(5)("test") in Scala 3 should work (just like bar).

Without these changes two migrations (of the use of the library in Scala 3) are required:

  1. While the library is using implicit usages like foo(5)("test") must be worked around.
  2. Then when the library evolves to using those workarounds can, finally, be removed.

Users like me which don’t like to go through the extra hassle of “migrating twice” can jump straight to the “end code” simply by using -source:future.

Cross-compiling should remain unaffected since it is very unlikely to be compiling the code under -source:future.

4 Likes