diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 9c580235a2e4..7c76211ca8ec 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -188,9 +188,17 @@ object ExtensionMethods { val companion = imeth.owner.companionModule val companionInfo = companion.info val candidates = companionInfo.decl(extensionName(imeth)).alternatives - val matching = - // See the documentation of `memberSignature` to understand why `.stripPoly.ensureMethodic` is needed here. - candidates filter (c => FullParameterization.memberSignature(c.info) == imeth.info.stripPoly.ensureMethodic.signature) + def matches(candidate: SingleDenotation) = + FullParameterization.memberSignature(candidate.info) == imeth.info.stripPoly.ensureMethodic.signature + // See the documentation of `memberSignature` to understand why `.stripPoly.ensureMethodic` is needed here. + && (if imeth.targetName == imeth.name then + // imeth does not have a @targetName annotation, candidate should not have one either + candidate.symbol.targetName == candidate.symbol.name + else + // imeth has a @targetName annotation, candidate's target name must match + imeth.targetName == candidate.symbol.targetName + ) + val matching = candidates.filter(matches) assert(matching.nonEmpty, i"""no extension method found for: | @@ -203,6 +211,9 @@ object ExtensionMethods { | Candidates (signatures normalized): | | ${candidates.map(c => s"${c.name}:${c.info.signature}:${FullParameterization.memberSignature(c.info)}").mkString("\n")}""") + if matching.tail.nonEmpty then + // this case will report a "have the same erasure" error later at erasure pahse + report.log(i"mutiple extension methods match $imeth: ${candidates.map(c => i"${c.name}:${c.info}")}") matching.head.symbol.asTerm } } diff --git a/tests/neg/i16464.scala b/tests/neg/i16464.scala new file mode 100644 index 000000000000..dfc4cd3da3c3 --- /dev/null +++ b/tests/neg/i16464.scala @@ -0,0 +1,6 @@ + +implicit final class SomeOps(e: Int) extends AnyVal: + def -(other: Seq[Int]) = List(1) + def -(other: Seq[Long]) = List(2) // error: double definition + +def main(): Unit = 1 - Seq.empty[Int] diff --git a/tests/pos/i16464.scala b/tests/pos/i16464.scala new file mode 100644 index 000000000000..a1bcabd33ace --- /dev/null +++ b/tests/pos/i16464.scala @@ -0,0 +1,26 @@ +import scala.annotation.targetName + +object test1: + implicit final class SomeOps(e: Int) extends AnyVal: + @targetName("a") + def -(other: Seq[Int]) = List(1) + @targetName("b") + def -(other: Seq[Long]) = List(2) + + def main(): Unit = 1 - Seq.empty[Int] + +object test2: + implicit final class SomeOps(e: Int) extends AnyVal: + @targetName("a") + def -(other: Seq[Int]) = List(1) + def -(other: Seq[Long]) = List(2) + + def main(): Unit = 1 - Seq.empty[Int] + +object test3: + implicit final class SomeOps(e: Int) extends AnyVal: + def -(other: Seq[Int]) = List(1) + @targetName("b") + def -(other: Seq[Long]) = List(2) + + def main(): Unit = 1 - Seq.empty[Int] diff --git a/tests/run/i16464.scala b/tests/run/i16464.scala new file mode 100644 index 000000000000..15714aa53765 --- /dev/null +++ b/tests/run/i16464.scala @@ -0,0 +1,10 @@ +import scala.annotation.targetName + +implicit final class SomeOps(e: Int) extends AnyVal: + @targetName("a") + def -(other: Seq[Int]) = List(1) + @targetName("b") + def -(other: Seq[Long]) = List(2) + +@main +def Test(): Unit = 1 - Seq.empty[Int] \ No newline at end of file