Skip to content

Commit 11a0325

Browse files
committed
Take expected type into account when typing a sequence argument
Given an expected type `*T`, we allow a sequence argument `xs: _*` to be either a `Seq[T]` or an `Array[_ <: T]`, irrespective of whether the method we're calling is a Java or Scala method. So far we typed sequence arguments without an expected type, meaning that adaptation did not take place. But thanks to #8635, we can type them with an expected type of `Seq[T] | Array[_ <: T]` and type inference works out. This is what this commit does.
1 parent 1a9c9eb commit 11a0325

File tree

6 files changed

+49
-12
lines changed

6 files changed

+49
-12
lines changed

compiler/src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,12 +389,14 @@ class TypeApplications(val self: Type) extends AnyVal {
389389
}
390390

391391
/** If this is a repeated parameter `*T`, translate it to either `Seq[T]` or
392-
* `Array[? <: T]` depending on the value of `toArray`, keep other types as
393-
* they are.
392+
* `Array[? <: T]` depending on the value of `toArray`, if this is a wildcard
393+
* prototype then treat it like `*<?>`, keep other types as they are.
394394
*/
395395
def translateFromRepeated(toArray: Boolean)(using Context): Type =
396-
if self.isRepeatedParam then
397-
val seqClass = if (toArray) defn.ArrayClass else defn.SeqClass
396+
val seqClass = if (toArray) defn.ArrayClass else defn.SeqClass
397+
if self.isInstanceOf[WildcardType] then
398+
seqClass.typeRef.appliedTo(WildcardType)
399+
else if self.isRepeatedParam then
398400
// We want `Array[? <: T]` because arrays aren't covariant until after
399401
// erasure. See `tests/pos/i5140`.
400402
translateParameterized(defn.RepeatedParamClass, seqClass, wildcardArg = toArray)

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -728,19 +728,19 @@ class Typer extends Namer
728728

729729
if (untpd.isWildcardStarArg(tree)) {
730730
def typedWildcardStarArgExpr = {
731+
// A sequence argument `xs: _*` can be either a `Seq[T]` or an `Array[_ <: T]`,
732+
// irrespective of whether the method we're calling is a Java or Scala method,
733+
// so the expected type is the union `Seq[T] | Array[_ <: T]`.
731734
val ptArg =
735+
// FIXME(#8680): Quoted patterns do not support Array repeated arguments
732736
if (ctx.mode.is(Mode.QuotedPattern)) pt.translateFromRepeated(toArray = false)
733-
else WildcardType
737+
else pt.translateFromRepeated(toArray = false) | pt.translateFromRepeated(toArray = true)
734738
val tpdExpr = typedExpr(tree.expr, ptArg)
735739
tpdExpr.tpe.widenDealias match {
736740
case defn.ArrayOf(_) =>
737-
val starType = defn.ArrayType.appliedTo(WildcardType)
738-
val exprAdapted = adapt(tpdExpr, starType)
739-
arrayToRepeated(exprAdapted)
741+
arrayToRepeated(tpdExpr)
740742
case _ =>
741-
val starType = defn.SeqType.appliedTo(defn.AnyType)
742-
val exprAdapted = adapt(tpdExpr, starType)
743-
seqToRepeated(exprAdapted)
743+
seqToRepeated(tpdExpr)
744744
}
745745
}
746746
cases(

tests/pos/sequence-argument/B_2.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import scala.reflect.ClassTag
2+
import scala.language.implicitConversions
3+
4+
object B {
5+
def doubleSeq[T](x: T): Seq[T] = Seq(x, x)
6+
def doubleArray[T: ClassTag](x: T): Array[T] = Array(x, x)
7+
8+
def box(args: Integer*): Unit = {}
9+
def widen(args: Long*): Unit = {}
10+
def conv(args: Y*): Unit = {}
11+
12+
box(doubleSeq(1): _*)
13+
box(doubleArray(1): _*)
14+
Java_2.box(doubleSeq(1): _*)
15+
Java_2.box(doubleArray(1): _*)
16+
17+
widen(doubleSeq(1): _*)
18+
widen(doubleArray(1): _*)
19+
Java_2.widen(doubleSeq(1): _*)
20+
Java_2.widen(doubleArray(1): _*)
21+
22+
implicit def xToY(x: X): Y = new Y
23+
val x: X = new X
24+
conv(doubleSeq(x): _*)
25+
conv(doubleArray(x): _*)
26+
Java_2.conv(doubleSeq(x): _*)
27+
Java_2.conv(doubleArray(x): _*)
28+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public class Java_2 {
2+
public static void box(Integer ...args) {}
3+
public static void widen(Long... args) {}
4+
public static void conv(Y... args) {}
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class X
2+
class Y

0 commit comments

Comments
 (0)