Skip to content

Commit 579c01b

Browse files
Remove Override flag from varargs forwarders when there is no forwarder
to override
1 parent 19cf871 commit 579c01b

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
4343
val hasAnnotation = hasVarargsAnnotation(sym)
4444
val hasRepeatedParam = hasRepeatedParams(sym)
4545
if hasRepeatedParam then
46-
if isJavaVarargsOverride || hasAnnotation || parentHasAnnotation(sym) then
46+
val parentHasAnnotation = parentHasVarargsAnnotation(sym)
47+
if isJavaVarargsOverride || hasAnnotation || parentHasAnnotation then
4748
// java varargs are more restrictive than scala's
4849
// see https://github.com/scala/bug/issues/11714
4950
val validJava = isValidJavaVarArgs(sym.info)
@@ -54,7 +55,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
5455
|""".stripMargin,
5556
sym.sourcePos)
5657
else
57-
addVarArgsForwarder(sym, isJavaVarargsOverride, hasAnnotation)
58+
addVarArgsForwarder(sym, isJavaVarargsOverride, hasAnnotation, parentHasAnnotation)
5859
else if hasAnnotation then
5960
report.error("A method without repeated parameters cannot be annotated with @varargs", sym.sourcePos)
6061
end
@@ -79,7 +80,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
7980

8081
private def hasVarargsAnnotation(sym: Symbol)(using Context) = sym.hasAnnotation(defn.VarargsAnnot)
8182

82-
private def parentHasAnnotation(sym: Symbol)(using Context) = sym.allOverriddenSymbols.exists(hasVarargsAnnotation)
83+
private def parentHasVarargsAnnotation(sym: Symbol)(using Context) = sym.allOverriddenSymbols.exists(hasVarargsAnnotation)
8384

8485
private def isVarargsMethod(sym: Symbol)(using Context) =
8586
hasVarargsAnnotation(sym) ||
@@ -259,14 +260,16 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
259260
*
260261
* @param original the original method symbol
261262
* @param isBridge true if we are generating a "bridge" (synthetic override forwarder)
263+
* @param hasAnnotation true if the method is annotated with `@varargs`
264+
* @param parentHasAnnotation true if the method overrides a method that is annotated with `@varargs`
262265
*
263266
* A forwarder is necessary because the following holds:
264267
* - the varargs in `original` will change from `RepeatedParam[T]` to `Seq[T]` after this phase
265268
* - _but_ the callers of the method expect its varargs to be changed to `Array[? <: T]`
266269
* The solution is to add a method that converts its argument from `Array[? <: T]` to `Seq[T]` and
267270
* forwards it to the original method.
268271
*/
269-
private def addVarArgsForwarder(original: Symbol, isBridge: Boolean, hasAnnotation: Boolean)(using Context): Unit =
272+
private def addVarArgsForwarder(original: Symbol, isBridge: Boolean, hasAnnotation: Boolean, parentHasAnnotation: Boolean)(using Context): Unit =
270273
val owner = original.owner
271274
if !owner.isClass then
272275
report.error("inner methods cannot be annotated with @varargs", original.sourcePos)
@@ -281,7 +284,10 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
281284
// The java-compatible forwarder symbol
282285
val forwarder =
283286
original.copy(
284-
flags = if isBridge then flags | Artifact else flags,
287+
flags =
288+
if isBridge then flags | Artifact
289+
else if hasAnnotation && !parentHasAnnotation then flags &~ Override
290+
else flags,
285291
info = toJavaVarArgs(original.info)
286292
).asTerm
287293

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import scala.annotation.varargs
2+
3+
abstract class NoAnnot {
4+
// java varargs forwarder: no
5+
def f(args: String*): Unit
6+
}
7+
class B1 extends NoAnnot {
8+
// java varargs forwarder: no
9+
override def f(args: String*) = ()
10+
}
11+
class B2 extends NoAnnot {
12+
// java varargs forwarder: yes, but it doesn't override anything
13+
@varargs
14+
override def f(args: String*) = ()
15+
}
16+
class C1 extends B2 {
17+
// java varargs forwarder: yes, overrides parent forwarder
18+
override def f(args: String*) = ()
19+
}
20+
class C2 extends B2 {
21+
// java varargs forwarder: yes, overrides parent forwarder
22+
@varargs
23+
override def f(args: String*) = ()
24+
}

0 commit comments

Comments
 (0)