Skip to content

Commit fb9be5d

Browse files
committed
Take @TargetNAME into account when resolving extension methods of value classes
Before target name we only matched on signatures. This was OK, since multiple extension methods of the same class must be different, otherwise we will get a "have the same erasure" error later at erasurePhase. But with @TargetNAME that's now a legal situation that needs to be resolve correctly. We do this by propagating the target name to the extension method and verifiying that the target names of the original and extension methods match. Fixes scala#16464
1 parent 716d93d commit fb9be5d

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,12 @@ object ExtensionMethods {
188188
val companion = imeth.owner.companionModule
189189
val companionInfo = companion.info
190190
val candidates = companionInfo.decl(extensionName(imeth)).alternatives
191-
val matching =
192-
// See the documentation of `memberSignature` to understand why `.stripPoly.ensureMethodic` is needed here.
193-
candidates filter (c => FullParameterization.memberSignature(c.info) == imeth.info.stripPoly.ensureMethodic.signature)
191+
def matches(candidate: SingleDenotation) =
192+
FullParameterization.memberSignature(candidate.info) == imeth.info.stripPoly.ensureMethodic.signature
193+
// See the documentation of `memberSignature` to understand why `.stripPoly.ensureMethodic` is needed here.
194+
&& (imeth.targetName == imeth.name // if no targetname was given, signatures alone decide
195+
|| imeth.targetName == candidate.symbol.targetName) // otherwise targetnames must match
196+
val matching = candidates.filter(matches)
194197
assert(matching.nonEmpty,
195198
i"""no extension method found for:
196199
|
@@ -203,6 +206,9 @@ object ExtensionMethods {
203206
| Candidates (signatures normalized):
204207
|
205208
| ${candidates.map(c => s"${c.name}:${c.info.signature}:${FullParameterization.memberSignature(c.info)}").mkString("\n")}""")
209+
if matching.tail.nonEmpty then
210+
// this case will report a "have the same erasure" error later at erasure pahse
211+
report.log(i"mutiple extension methods match $imeth: ${candidates.map(c => i"${c.name}:${c.info}")}")
206212
matching.head.symbol.asTerm
207213
}
208214
}

tests/pos/i16464.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.annotation.targetName
2+
3+
implicit final class SomeOps(e: Int) extends AnyVal:
4+
@targetName("a")
5+
def -(other: Seq[Int]) = List(1)
6+
@targetName("b")
7+
def -(other: Seq[Long]) = List(2)
8+
9+
@main
10+
def main(): Unit = 1 - Seq.empty[Int]

0 commit comments

Comments
 (0)