From 8130c32734c0008b664780a708f25d0cda6a6ed6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 13 Jul 2021 17:49:30 +0200 Subject: [PATCH 1/2] Handle overloaded members when generating Java varargs bridges Fixes #13043 --- .../tools/dotc/transform/ElimRepeated.scala | 25 ++++++++++++++++--- tests/pos/i13043/Impl.scala | 5 ++++ tests/pos/i13043/Intf.java | 5 ++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i13043/Impl.scala create mode 100644 tests/pos/i13043/Intf.java diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index 8068e88bf874..6e2c260e9f5d 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package transform import core._ @@ -76,7 +77,23 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => override def infoMayChange(sym: Symbol)(using Context): Boolean = sym.is(Method) - private def overridesJava(sym: Symbol)(using Context) = sym.allOverriddenSymbols.exists(_.is(JavaDefined)) + /** Does `sym` override a symbol defined in a Java class? One might think that + * this can be expressed as + * + * sym.allOverriddenSymbols.exists(_.is(JavaDefined)) + * + * but that does not work, since `allOverriddenSymbols` gets confused because the + * signatures of a Java varargs method and a Scala varargs override are not the same. + */ + private def overridesJava(sym: Symbol)(using Context) = + sym.owner.info.baseClasses.drop(1).exists { bc => + bc.is(JavaDefined) && { + val other = bc.info.nonPrivateDecl(sym.name) + other.hasAltWith { alt => + sym.owner.thisType.memberInfo(alt.symbol).matchesLoosely(sym.info) + } + } + } private def hasVarargsAnnotation(sym: Symbol)(using Context) = sym.hasAnnotation(defn.VarargsAnnot) @@ -85,7 +102,8 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => private def isVarargsMethod(sym: Symbol)(using Context) = hasVarargsAnnotation(sym) || hasRepeatedParams(sym) && - (sym.allOverriddenSymbols.exists(s => s.is(JavaDefined) || hasVarargsAnnotation(s))) + overridesJava(sym) + || sym.allOverriddenSymbols.exists(hasVarargsAnnotation) /** Eliminate repeated parameters from method types. */ private def elimRepeated(tp: Type, isJava: Boolean)(using Context): Type = tp.stripTypeVar match @@ -292,6 +310,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => report.error(s"$src produces a forwarder method that conflicts with ${conflict.showDcl}", original.srcPos) case Nil => forwarder.enteredAfter(thisPhase) + end addVarArgsForwarder /** Convert type from Scala to Java varargs method */ private def toJavaVarArgs(tp: Type)(using Context): Type = tp match diff --git a/tests/pos/i13043/Impl.scala b/tests/pos/i13043/Impl.scala new file mode 100644 index 000000000000..7db75ee99d89 --- /dev/null +++ b/tests/pos/i13043/Impl.scala @@ -0,0 +1,5 @@ +class Impl extends Intf { + override def thing(x: Int) = ??? + override def thing(y: String*) = ??? + override def thing2(y: String*) = ??? +} \ No newline at end of file diff --git a/tests/pos/i13043/Intf.java b/tests/pos/i13043/Intf.java new file mode 100644 index 000000000000..8b845bdca146 --- /dev/null +++ b/tests/pos/i13043/Intf.java @@ -0,0 +1,5 @@ +interface Intf { + public void thing(int x); + public void thing(String... y); + public void thing2(String... y); +} \ No newline at end of file From abf4b45f4735664249fc85e95d38915515e0ac5e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 15 Jul 2021 12:29:20 +0200 Subject: [PATCH 2/2] Add missing parens --- compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index 6e2c260e9f5d..429c0e7445b2 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -100,10 +100,9 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => private def parentHasVarargsAnnotation(sym: Symbol)(using Context) = sym.allOverriddenSymbols.exists(hasVarargsAnnotation) private def isVarargsMethod(sym: Symbol)(using Context) = - hasVarargsAnnotation(sym) || - hasRepeatedParams(sym) && - overridesJava(sym) - || sym.allOverriddenSymbols.exists(hasVarargsAnnotation) + hasVarargsAnnotation(sym) + || hasRepeatedParams(sym) + && (overridesJava(sym) || sym.allOverriddenSymbols.exists(hasVarargsAnnotation)) /** Eliminate repeated parameters from method types. */ private def elimRepeated(tp: Type, isJava: Boolean)(using Context): Type = tp.stripTypeVar match