Skip to content

Commit 0c89b74

Browse files
committed
Fix #4785: change typing rule for _* args
In expression position, if a tree is of the form `expr: _*`, try to type `expr` as an `Array` and as a `Seq` if there are errors
1 parent 2548ef0 commit 0c89b74

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,6 @@ class Definitions {
345345
def Predef_classOf(implicit ctx: Context) = Predef_classOfR.symbol
346346
lazy val Predef_undefinedR = ScalaPredefModule.requiredMethodRef("???")
347347
def Predef_undefined(implicit ctx: Context) = Predef_undefinedR.symbol
348-
// The set of all wrap{X, Ref}Array methods, where X is a value type
349-
val Predef_wrapArray = new PerRun[collection.Set[Symbol]]({ implicit ctx =>
350-
val methodNames = ScalaValueTypes.map(TreeGen.wrapArrayMethodName) + nme.wrapRefArray
351-
methodNames.map(ScalaPredefModule.requiredMethodRef(_).symbol)
352-
})
353348

354349
lazy val ScalaRuntimeModuleRef = ctx.requiredModuleRef("scala.runtime.ScalaRunTime")
355350
def ScalaRuntimeModule(implicit ctx: Context) = ScalaRuntimeModuleRef.symbol

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ class TypeApplications(val self: Type) extends AnyVal {
492492
}
493493

494494
/** The element type of a sequence or array */
495-
def elemType(implicit ctx: Context): Type = self match {
495+
def elemType(implicit ctx: Context): Type = self.widenDealias match {
496496
case defn.ArrayOf(elemtp) => elemtp
497497
case JavaArrayType(elemtp) => elemtp
498498
case _ => self.baseType(defn.SeqClass).argInfos.headOption.getOrElse(NoType)

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,14 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
8585
val args1 = tree.args.zipWithConserve(formals) { (arg, formal) =>
8686
arg match {
8787
case arg: Typed if isWildcardStarArg(arg) =>
88-
if (tree.fun.symbol.is(JavaDefined) && arg.expr.tpe.derivesFrom(defn.SeqClass))
89-
seqToArray(arg.expr, formal.underlyingIfRepeated(isJava = true))
90-
else arg.expr
88+
val isJavaDefined = tree.fun.symbol.is(JavaDefined)
89+
val expr = arg.expr
90+
if (isJavaDefined && expr.tpe.derivesFrom(defn.SeqClass))
91+
seqToArray(expr, formal.underlyingIfRepeated(isJava = true))
92+
else if (!isJavaDefined && expr.tpe.derivesFrom(defn.ArrayClass))
93+
arrayToSeq(expr)
94+
else
95+
expr
9196
case arg => arg
9297
}
9398
}
@@ -98,12 +103,10 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
98103
private def seqToArray(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree match {
99104
case SeqLiteral(elems, elemtpt) =>
100105
JavaSeqLiteral(elems, elemtpt)
101-
case app@Apply(fun, args) if defn.Predef_wrapArray().contains(fun.symbol) => // rewrite a call to `wrapXArray(arr)` to `arr`
102-
args.head
103106
case _ =>
104107
val elemType = tree.tpe.elemType
105108
var elemClass = elemType.classSymbol
106-
if (defn.NotRuntimeClasses contains elemClass) elemClass = defn.ObjectClass
109+
if (defn.NotRuntimeClasses.contains(elemClass)) elemClass = defn.ObjectClass
107110
ref(defn.DottyArraysModule)
108111
.select(nme.seqToArray)
109112
.appliedToType(elemType)
@@ -112,6 +115,10 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
112115
// Because of phantomclasses, the Java array's type might not conform to the return type
113116
}
114117

118+
/** Convert Java array argument to Scala Seq of type `pt` */
119+
private def arrayToSeq(tree: Tree)(implicit ctx: Context): Tree =
120+
TreeGen.wrapArray(tree, tree.tpe.elemType)
121+
115122
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree =
116123
transformTypeOfTree(tree)
117124

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,11 +557,26 @@ class Typer extends Namer
557557
else typed(tree.expr, tpt.tpe.widenSkolem)
558558
assignType(cpy.Typed(tree)(expr1, tpt), underlyingTreeTpe)
559559
}
560-
if (untpd.isWildcardStarArg(tree))
560+
if (untpd.isWildcardStarArg(tree)) {
561+
/** If tree is of the form `expr: _*`, try to type `expr` as an `Array`
562+
* and as a `Seq` if there are errors.
563+
*/
564+
def typedWildcardStarArgExpr = {
565+
def asSeq(implicit ctx: Context) =
566+
seqToRepeated(typedExpr(tree.expr, defn.SeqType.appliedTo(defn.AnyType)))
567+
def asArray(elemTpe: Type)(implicit ctx: Context) = {
568+
val expr = typedExpr(tree.expr, defn.ArrayType.appliedTo(elemTpe))
569+
Typed(expr, TypeTree(defn.RepeatedParamType.appliedTo(elemTpe)))
570+
}
571+
val elemTpe = pt.elemType
572+
if (elemTpe.exists) tryAlternatively[Tree](asArray(elemTpe)(_))(asSeq(_))
573+
else asSeq
574+
}
561575
cases(
562576
ifPat = ascription(TypeTree(defn.RepeatedParamType.appliedTo(pt)), isWildcard = true),
563-
ifExpr = seqToRepeated(typedExpr(tree.expr, defn.SeqType.appliedTo(defn.AnyType))),
577+
ifExpr = typedWildcardStarArgExpr,
564578
wildName = nme.WILDCARD_STAR)
579+
}
565580
else {
566581
def typedTpt = checkSimpleKinded(typedType(tree.tpt))
567582
def handlePattern: Tree = {

0 commit comments

Comments
 (0)