@@ -114,22 +114,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
114114 if lastIdx >= 0 then
115115 val last = paramTypes(lastIdx)
116116 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))
133118 else paramTypes
134119 else paramTypes
135120 tp.derivedLambdaType(paramNames, paramTypes1, resultType1)
@@ -144,8 +129,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
144129 val isJavaDefined = tree.fun.symbol.is(JavaDefined )
145130 val tpe = arg.expr.tpe
146131 if isJavaDefined then
147- val pt = tree.fun.tpe.widen.firstParamTypes.last
148- adaptToArray(arg.expr, pt.elemType.bounds.hi)
132+ adaptToArray(arg.expr)
149133 else if tpe.derivesFrom(defn.ArrayClass ) then
150134 arrayToSeq(arg.expr)
151135 else
@@ -154,58 +138,25 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
154138 }
155139 cpy.Apply (tree)(tree.fun, args)
156140
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
159142 case SeqLiteral (elems, elemtpt) =>
160- JavaSeqLiteral (elems, elemtpt)
143+ JavaSeqLiteral (elems, elemtpt).withSpan(tree.span)
161144 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
204149 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)))
209160
210161 /** Convert an Array into a scala.Seq */
211162 private def arrayToSeq (tree : Tree )(using Context ): Tree =
0 commit comments