Skip to content

Commit 3379e4b

Browse files
authored
Merge pull request #5192 from dotty-staging/fix-5191
Fix #5191: Don't lift the receiver of a call to a method with varargs
2 parents 466bdb8 + 379ad18 commit 3379e4b

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,23 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
228228

229229
/** Whether `liftFun` is needed? It is the case if default arguments are used.
230230
*/
231-
protected def needLiftFun: Boolean =
231+
protected def needLiftFun: Boolean = {
232+
def requiredArgNum(tp: Type): Int = tp.widen match {
233+
case funType: MethodType =>
234+
val paramInfos = funType.paramInfos
235+
val argsNum = paramInfos.size
236+
if (argsNum >= 1 && paramInfos.last.isRepeatedParam)
237+
// Repeated arguments do not count as required arguments
238+
argsNum - 1
239+
else
240+
argsNum
241+
case funType: PolyType => requiredArgNum(funType.resultType)
242+
case tp => args.size
243+
}
244+
232245
!isJavaAnnotConstr(methRef.symbol) &&
233-
args.size < reqiredArgNum(funType)
246+
args.size < requiredArgNum(funType)
247+
}
234248

235249
/** A flag signalling that the typechecking the application was so far successful */
236250
private[this] var _ok = true
@@ -250,12 +264,6 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
250264
case tp => tp //was: funType
251265
}
252266

253-
def reqiredArgNum(tp: Type): Int = tp.widen match {
254-
case funType: MethodType => funType.paramInfos.size
255-
case funType: PolyType => reqiredArgNum(funType.resultType)
256-
case tp => args.size
257-
}
258-
259267
lazy val liftedFunType =
260268
if (needLiftFun) {
261269
liftFun()

compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,4 +475,29 @@ class TestBCode extends DottyBytecodeTest {
475475
diffInstructions(testInstructions, refInstructions))
476476
}
477477
}
478+
479+
/** Test that the receiver of a call to a method with varargs is not unnecessarily lifted */
480+
@Test def i5191 = {
481+
val source =
482+
"""class Test {
483+
| def foo(args: String*): String = ""
484+
| def self = this
485+
|
486+
| def test = self.foo()
487+
|}
488+
""".stripMargin
489+
490+
checkBCode(source) { dir =>
491+
val clsIn = dir.lookupName("Test.class", directory = false).input
492+
val clsNode = loadClassNode(clsIn)
493+
val method = getMethod(clsNode, "test")
494+
495+
val liftReceiver = instructionsFromMethod(method).exists {
496+
case VarOp(Opcodes.ASTORE, _) => true // receiver lifted in local val
497+
case _ => false
498+
}
499+
assertFalse("Receiver of a call to a method with varargs is unnecessarily lifted",
500+
liftReceiver)
501+
}
502+
}
478503
}

0 commit comments

Comments
 (0)