Skip to content

Commit

Permalink
Fix handling of lifted varargs in ElimRepeated
Browse files Browse the repository at this point in the history
Fixes #15078
  • Loading branch information
TheElectronWill committed Jun 25, 2022
1 parent e4b63e3 commit 8d2f6c0
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 11 deletions.
24 changes: 14 additions & 10 deletions compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,21 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
tp

override def transformApply(tree: Apply)(using Context): Tree =
val args = tree.args.mapConserve {
case arg: Typed if isWildcardStarArg(arg) =>
val args = tree.args.mapConserve { arg =>
if isWildcardStarArg(arg) then
val expr = arg match
case t: Typed => t.expr
case _ => arg // if the argument has been lifted it's not a Typed (often it's an Ident)

val isJavaDefined = tree.fun.symbol.is(JavaDefined)
val tpe = arg.expr.tpe
if isJavaDefined then
adaptToArray(arg.expr)
else if tpe.derivesFrom(defn.ArrayClass) then
arrayToSeq(arg.expr)
adaptToArray(expr)
else if expr.tpe.derivesFrom(defn.ArrayClass) then
arrayToSeq(expr)
else
arg.expr
case arg => arg
expr
else
arg
}
cpy.Apply(tree)(tree.fun, args)

Expand Down Expand Up @@ -287,9 +291,9 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
val array = tp.translateFromRepeated(toArray = true) // Array[? <: T]
val element = array.elemType.hiBound // T


if element <:< defn.AnyRefType
|| ctx.mode.is(Mode.SafeNulls) && element.stripNull <:< defn.AnyRefType
|| element.typeSymbol.isPrimitiveValueClass then array
|| element.typeSymbol.isPrimitiveValueClass
then array
else defn.ArrayOf(TypeBounds.upper(AndType(element, defn.AnyRefType))) // Array[? <: T & AnyRef]
}
3 changes: 2 additions & 1 deletion compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ class CoverageTests:
def computeCoverageInTmp(inputFile: Path, sourceRoot: Path, run: Boolean)(using TestGroup): Path =
val target = Files.createTempDirectory("coverage")
val options = defaultOptions.and("-Ycheck:instrumentCoverage", "-coverage-out", target.toString, "-sourceroot", sourceRoot.toString)
val test = compileFile(inputFile.toString, options)
if run then
val test = compileDir(inputFile.getParent.toString, options)
test.checkRuns()
else
val test = compileFile(inputFile.toString, options)
test.checkCompile()
target

Expand Down
7 changes: 7 additions & 0 deletions tests/coverage/run/varargs/JavaVarargs_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class JavaVarargs_1 {
static void method(String... args) {}

static Object multiple(Object first, String... others) {
return String.valueOf(first) + others.length;
}
}
3 changes: 3 additions & 0 deletions tests/coverage/run/varargs/test_1.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
first0
first0
first3
20 changes: 20 additions & 0 deletions tests/coverage/run/varargs/test_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import java.nio.file.Files
import java.io.File

def repeated(s: String*) = ()

def f(s: String) = s

@main
def Test =
repeated()
repeated(f(""), "b")
JavaVarargs_1.method()
JavaVarargs_1.method("")

var m = JavaVarargs_1.multiple("first")
println(m)
m = JavaVarargs_1.multiple(f("first"))
println(m)
m = JavaVarargs_1.multiple(f("first"), "a", "b", "c")
println(m)
293 changes: 293 additions & 0 deletions tests/coverage/run/varargs/test_1.scoverage.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
# Coverage data, format version: 3.0
# Statement data:
# - id
# - source path
# - package name
# - class name
# - class type (Class, Object or Trait)
# - full class name
# - method name
# - start offset
# - end offset
# - line number
# - symbol name
# - tree name
# - is branch
# - invocations count
# - is ignored
# - description (can be multi-line)
# ' ' sign
# ------------------------------------------
0
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
repeated
48
60
3
repeated
DefDef
false
0
false
def repeated

1
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
f
79
84
5
f
DefDef
false
0
false
def f

2
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
120
130
9
repeated
Apply
false
0
false
repeated()

3
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
142
147
10
f
Apply
false
0
false
f("")

4
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
133
153
10
repeated
Apply
false
0
false
repeated(f(""), "b")

5
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
156
178
11
method
Apply
false
0
false
JavaVarargs_1.method()

6
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
181
205
12
method
Apply
false
0
false
JavaVarargs_1.method("")

7
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
217
248
14
multiple
Apply
false
0
false
JavaVarargs_1.multiple("first")

8
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
251
261
15
println
Apply
false
0
false
println(m)

9
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
291
301
16
f
Apply
false
0
false
f("first")

10
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
268
302
16
multiple
Apply
false
0
false
JavaVarargs_1.multiple(f("first"))

11
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
305
315
17
println
Apply
false
0
false
println(m)

12
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
345
355
18
f
Apply
false
0
false
f("first")

13
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
322
371
18
multiple
Apply
false
0
false
JavaVarargs_1.multiple(f("first"), "a", "b", "c")

14
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
374
384
19
println
Apply
false
0
false
println(m)

15
varargs/test_1.scala
<empty>
test_1$package$
Object
<empty>.test_1$package$
Test
101
115
8
Test
DefDef
false
0
false
@main
def Test

0 comments on commit 8d2f6c0

Please sign in to comment.