Description
Compiler version
3.2.2 (and still in 3.3.0-RC2)
Minimized code
Scastie: https://scastie.scala-lang.org/Ichoran/fgRflBYNRciNP6bBG9WtSw/14
object One:
extension (s: String)
def wow: Unit = println(s)
object Two:
extension (i: Int)
def wow: Unit = println(i)
object Three:
extension (s: String)
def wow: Unit = println(s)
extension (i: Int)
def wow: Unit = println(i)
object Four:
implicit class WowString(s: String):
def wow: Unit = println(s)
object Five:
implicit class WowInt(i: Int):
def wow: Unit = println(i)
object Compiles:
import Three._
def test: Unit =
5.wow
"five".wow
object AlsoCompiles:
import Four._
import Five._
def test: Unit =
5.wow
"five".wow
object Fails:
import One._
import Two._
def test: Unit =
5.wow
"five".wow
Output
value wow is not a member of Int.
An extension method was tried, but could not be fully constructed:
Playground.Two.wow(5) failed with
Reference to wow is ambiguous,
it is both imported by import Playground.One._
and imported subsequently by import Playground.Two._
value wow is not a member of String.
An extension method was tried, but could not be fully constructed:
Playground.Two.wow("five") failed with
Reference to wow is ambiguous,
it is both imported by import Playground.One._
and imported subsequently by import Playground.Two._
Expectation
Extension methods work when compiled independently for different argument types (in different namespaces).
Thus, extension methods should be equally usable when compiled independently or jointly, and also are equally as usable as the implicit class extension mechanism.
Actual Behavior
Independent compilation does not work with extension methods when the extension methods have the same name because the import ambiguity mechanism vetoes the successfully-resolved method call. (Note that the error message tells you that it has actually fully successfully dispatched the method based on type.)
This prevents removal of the implicit class
mechanism for extension methods, because implicit class
does not have this problem.
(It seems that this problem should have been reported already by now, but I can't find it. However, if this is not fixed, to be safe, nobody should use extension methods in any library, because it is impossible to predict when a collision might occur with some other library extending some other class. It's particularly acute with Java classes where you might want to define some obvious operation like +
, but someone might want to define it on Duration
and someone else might want to define it on Path
.)