@@ -114,22 +114,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
114
114
if lastIdx >= 0 then
115
115
val last = paramTypes(lastIdx)
116
116
if last.isRepeatedParam then
117
- // We need to be careful when handling Java repeated parameters
118
- // of the form `Object...` or `T...` where `T` is unbounded:
119
- // in both cases, `Object` will have been translated to `FromJavaObject`
120
- // to allow passing primitives as repeated arguments, but we can't
121
- // pass a primitive array as argument to such a method since the
122
- // parameter will be erased to `Object[]`. To handle this correctly we
123
- // drop usage of `FromJavaObject` as an element type here, the
124
- // tree transformer of this phase is then responsible for handling
125
- // mismatches by emitting the correct adaptation (cf `adaptToArray`).
126
- // See also the documentation of `FromJavaObjectSymbol`.
127
- val last1 =
128
- if isJava && last.elemType.isFromJavaObject then
129
- defn.ArrayOf (TypeBounds .upper(defn.ObjectType ))
130
- else
131
- last.translateFromRepeated(toArray = isJava)
132
- paramTypes.updated(lastIdx, last1)
117
+ paramTypes.updated(lastIdx, last.translateFromRepeated(toArray = isJava))
133
118
else paramTypes
134
119
else paramTypes
135
120
tp.derivedLambdaType(paramNames, paramTypes1, resultType1)
@@ -144,8 +129,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
144
129
val isJavaDefined = tree.fun.symbol.is(JavaDefined )
145
130
val tpe = arg.expr.tpe
146
131
if isJavaDefined then
147
- val pt = tree.fun.tpe.widen.firstParamTypes.last
148
- adaptToArray(arg.expr, pt.elemType.bounds.hi)
132
+ adaptToArray(arg.expr)
149
133
else if tpe.derivesFrom(defn.ArrayClass ) then
150
134
arrayToSeq(arg.expr)
151
135
else
@@ -154,58 +138,25 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
154
138
}
155
139
cpy.Apply (tree)(tree.fun, args)
156
140
157
- /** Convert sequence argument to Java array */
158
- private def seqToArray (tree : Tree )(using Context ): Tree = tree match
141
+ private def adaptToArray (tree : Tree )(implicit ctx : Context ): Tree = tree match
159
142
case SeqLiteral (elems, elemtpt) =>
160
- JavaSeqLiteral (elems, elemtpt)
143
+ JavaSeqLiteral (elems, elemtpt).withSpan(tree.span)
161
144
case _ =>
162
- val elemType = tree.tpe.elemType
163
- var elemClass = erasure(elemType).classSymbol
164
- if defn.NotRuntimeClasses .contains(elemClass) then
165
- elemClass = defn.ObjectClass
166
- end if
167
- ref(defn.DottyArraysModule )
168
- .select(nme.seqToArray)
169
- .appliedToType(elemType)
170
- .appliedTo(tree, clsOf(elemClass.typeRef))
171
-
172
- /** Adapt a Seq or Array tree to be a subtype of `Array[_ <: $elemPt]`.
173
- *
174
- * @pre `elemPt` must either be a super type of the argument element type or `Object`.
175
- * The special handling of `Object` is required to deal with the translation
176
- * of generic Java varargs in `elimRepeated`.
177
- */
178
- private def adaptToArray (tree : Tree , elemPt : Type )(implicit ctx : Context ): Tree =
179
- val elemTp = tree.tpe.elemType
180
- val elemTpMatches = elemTp <:< elemPt
181
- val treeIsArray = tree.tpe.derivesFrom(defn.ArrayClass )
182
- if elemTpMatches && treeIsArray then
183
- tree // No adaptation necessary
184
- else tree match
185
- case SeqLiteral (elems, elemtpt) =>
186
- // By the precondition, we only have mismatches if elemPt is Object, in
187
- // that case we use `FromJavaObject` as the element type to allow the
188
- // sequence literal to typecheck no matter the types of the elements,
189
- // Erasure will take care of any necessary boxing (see documentation
190
- // of `FromJavaObjectSymbol` for more information).
191
- val adaptedElemTpt = if elemTpMatches then elemtpt else TypeTree (defn.FromJavaObjectType )
192
- JavaSeqLiteral (elems, adaptedElemTpt).withSpan(tree.span)
193
- case _ =>
194
- if treeIsArray then
195
- // Convert an Array[T] to an Array[Object]
196
- ref(defn.ScalaRuntime_toObjectArray )
197
- .appliedTo(tree)
198
- else if elemTpMatches then
199
- // Convert a Seq[T] to an Array[$elemPt]
200
- ref(defn.DottyArraysModule )
201
- .select(nme.seqToArray)
202
- .appliedToType(elemPt)
203
- .appliedTo(tree, clsOf(elemPt))
145
+ val elemTp = tree.tpe.elemType
146
+ val adapted =
147
+ if tree.tpe.derivesFrom(defn.ArrayClass ) then
148
+ tree
204
149
else
205
- // Convert a Seq[T] to an Array[Object]
206
- ref(defn.ScalaRuntime_toArray )
207
- .appliedToType(elemTp)
208
- .appliedTo(tree)
150
+ ref(defn.DottyArraysModule )
151
+ .select(nme.seqToArray)
152
+ .appliedToType(elemTp)
153
+ .appliedTo(tree, clsOf(elemTp))
154
+ // This seemingly redundant type ascription is needed because the result
155
+ // type of `adapted` might be erased to `Object`, but we need to keep
156
+ // the precise result type at erasure for `Erasure.Boxing.cast` to adapt
157
+ // a primitive array into a reference array if needed.
158
+ // Test case in tests/run/t1360.scala.
159
+ Typed (adapted, TypeTree (defn.ArrayOf (elemTp)))
209
160
210
161
/** Convert an Array into a scala.Seq */
211
162
private def arrayToSeq (tree : Tree )(using Context ): Tree =
0 commit comments