Skip to content

Commit 721c97e

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 721c97e

File tree

5 files changed

+36
-16
lines changed

5 files changed

+36
-16
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/TypeAssigner.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,12 @@ trait TypeAssigner {
153153
if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) checkNoPrivateLeaks(sym, pos)
154154
else sym.info
155155

156-
def seqToRepeated(tree: Tree)(implicit ctx: Context): Tree =
157-
Typed(tree, TypeTree(tree.tpe.widen.translateParameterized(defn.SeqClass, defn.RepeatedParamClass)))
156+
private def toRepeated(tree: Tree, from: ClassSymbol)(implicit ctx: Context): Tree =
157+
Typed(tree, TypeTree(tree.tpe.widen.translateParameterized(from, defn.RepeatedParamClass)))
158+
159+
def seqToRepeated(tree: Tree)(implicit ctx: Context): Tree = toRepeated(tree, defn.SeqClass)
160+
161+
def arrayToRepeated(tree: Tree)(implicit ctx: Context): Tree = toRepeated(tree, defn.ArrayClass)
158162

159163
/** A denotation exists really if it exists and does not point to a stale symbol. */
160164
final def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = try

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,11 +557,25 @@ 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(implicit ctx: Context) =
568+
arrayToRepeated(typedExpr(tree.expr, defn.ArrayType.appliedTo(WildcardType)))
569+
570+
// we try asArray first because asSeq will succeed if the former succeed due
571+
// to the implicit conversion from Array to WrappedArray defined in Predef
572+
tryAlternatively[Tree](asArray(_))(asSeq(_))
573+
}
561574
cases(
562575
ifPat = ascription(TypeTree(defn.RepeatedParamType.appliedTo(pt)), isWildcard = true),
563-
ifExpr = seqToRepeated(typedExpr(tree.expr, defn.SeqType.appliedTo(defn.AnyType))),
576+
ifExpr = typedWildcardStarArgExpr,
564577
wildName = nme.WILDCARD_STAR)
578+
}
565579
else {
566580
def typedTpt = checkSimpleKinded(typedType(tree.tpt))
567581
def handlePattern: Tree = {

0 commit comments

Comments
 (0)