Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions library/src/scala/collection/BuildFrom.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import scala.annotation.implicitNotFound
import scala.collection.mutable.Builder
import scala.collection.immutable.WrappedString
import scala.reflect.ClassTag
import scala.annotation.experimental

/** Builds a collection of type `C` from elements of type `A` when a source collection of type `From` is available.
* Implicit instances of `BuildFrom` are available for all collection types.
Expand Down Expand Up @@ -84,6 +85,15 @@ object BuildFrom extends BuildFromLowPriority1 {
def newBuilder(from: Array[?]): Builder[A, Array[A]] = Factory.arrayFactory[A].newBuilder
}

@experimental
given buildFromIArray[A : ClassTag]: BuildFrom[IArray[Any], A, IArray[A]] =
// IArray[?] is unreducible wildcard, but as IArray is covariant its ok to use IArray[Any] here.
new BuildFrom[IArray[Any], A, IArray[A]]:
def fromSpecific(from: IArray[Any])(it: IterableOnce[A]^): IArray[A] =
// TODO: when IArray factory is added to library, delegate there.
IArray.unsafeFromArray(Factory.arrayFactory[A].fromSpecific(it))
def newBuilder(from: IArray[Any]): Builder[A, IArray[A]] = IArray.newBuilder[A]

implicit def buildFromView[A, B]: BuildFrom[View[A], B, View[B]] =
new BuildFrom[View[A], B, View[B]] {
def fromSpecific(from: View[A])(it: IterableOnce[B]^): View[B]^{it} = View.from(it)
Expand Down
2 changes: 2 additions & 0 deletions project/MiMaFilters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ object MiMaFilters {
// Additions that require a new minor version of the library
Build.mimaPreviousDottyVersion -> Seq(
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.caps.package#package.freeze"),
// IArray integration with Scala Collections:
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.BuildFrom.buildFromIArray"),
),

)
Expand Down
3 changes: 3 additions & 0 deletions tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ val experimentalDefinitionInLibrary = Set(

// New feature: Erased trait
"scala.compiletime.Erased",

// New API: BuildFrom[IArray[Any], T, IArray[T]]
"scala.collection.BuildFrom$.buildFromIArray",
)


Expand Down
26 changes: 26 additions & 0 deletions tests/run/IArrayOps-experimental-BuildFrom.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//> using options -experimental

import scala.collection.BuildFrom

def diffs(ns: IArray[Long]): IArray[Long] =
ns.lazyZip(ns.tail).map((a, b) => b - a)

def diffsB(ns: IArray[Long])(bf: BuildFrom[IArray[Long], Long, IArray[Long]]): IArray[Long] =
ns.lazyZip(ns.tail).map((a, b) => b - a)(using bf)

@main def Test: Unit =
val explicit: BuildFrom[IArray[Long], Long, IArray[Long]] =
scala.collection.BuildFrom.buildFromIArray[Long]

val contextual: BuildFrom[IArray[Long], Long, IArray[Long]] =
summon[BuildFrom[IArray[Long], Long, IArray[Long]]]

val contextualWide: BuildFrom[IArray[Any], Long, IArray[Long]] =
summon[BuildFrom[IArray[Any], Long, IArray[Long]]]

assert(explicit.getClass == contextual.getClass) // check default is same implementation.
assert(explicit.getClass == contextualWide.getClass) // check default is same implementation.

assert(diffs(IArray(1L, 3L, 6L, 10L)).sameElements(IArray(2L, 3L, 4L)))
assert(diffsB(IArray(1L, 3L, 6L, 10L))(contextual).sameElements(IArray(2L, 3L, 4L)))
assert(diffsB(IArray(1L, 3L, 6L, 10L))(contextualWide).sameElements(IArray(2L, 3L, 4L)))
Loading