Skip to content

Commit 39416d8

Browse files
committed
IArray.toArray: Deprecate broken method, add experimental overload
The cast in the original method is unsound. We can't change this method to return `Array[? <: T]` without breaking source-compatibility and even then the resulting method wouldn't be very useful, so deprecate it and introduces an overload that takes a ClassTag instead. This happens to be source-compatible because while these overloads are ambiguous, there exists an implicit conversion from IArray to ArraySeq which also provides `toArray`.
1 parent 1f4d125 commit 39416d8

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

library/src/scala/IArray.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package scala
22
import reflect.ClassTag
33

4+
import scala.annotation.experimental
45
import scala.collection.{LazyZip2, SeqView, Searching, Stepper, StepperShape}
56
import scala.collection.immutable.ArraySeq
67
import scala.collection.mutable.{ArrayBuilder, Builder}
@@ -249,9 +250,18 @@ object IArray:
249250
extension [T](arr: IArray[T]) def takeWhile(p: T => Boolean): IArray[T] =
250251
genericArrayOps(arr).takeWhile(p)
251252

252-
/** Returns a mutable copy of this immutable array. */
253-
extension [T](arr: IArray[T]) def toArray: Array[T] =
254-
arr.clone.asInstanceOf[Array[T]]
253+
// NOTE: these two overloads are never selected when calling toArray on an
254+
// IArray because they're considered ambiguous, but such calls still typecheck
255+
// because of the implicit conversion `genericWrapArray`.
256+
extension [T](arr: IArray[T])
257+
/** Returns a mutable copy of this immutable array. */
258+
@deprecated("This method implementation is incorrect and calling it can crash your program, please use the other overload.", "3.0.1")
259+
def toArray: Array[T] =
260+
arr.clone.asInstanceOf[Array[T]]
261+
/** Returns a mutable copy of this immutable array. */
262+
@experimental
263+
def toArray[U >: T: ClassTag]: Array[U] =
264+
Array.copyAs(arr, arr.length)
255265

256266
extension [T](arr: IArray[T])
257267
def ++[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr) ++ suffix.toSeq

project/MiMaFilters.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ object MiMaFilters {
1515
exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#SymbolMethods.typeMembers"),
1616
exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#TermParamClauseMethods.isErased"),
1717
exclude[DirectMissingMethodProblem]("scala.quoted.Type.valueOfTuple"),
18+
exclude[DirectMissingMethodProblem]("scala.IArray#package#IArray.toArray"),
1819
exclude[MissingClassProblem]("scala.annotation.experimental"),
1920
exclude[MissingClassProblem]("scala.annotation.internal.ErasedParam"),
2021
exclude[MissingClassProblem]("scala.annotation.internal.ErasedParam"),

tests/run/i12597.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@main def Test =
2+
val a: IArray[Int] = IArray(2)
3+
val b: IArray[Any] = a
4+
val c = b.toArray
5+
c(0) = ""

0 commit comments

Comments
 (0)