@@ -16,6 +16,8 @@ import scala.annotation.implicitNotFound
1616import scala .collection .mutable .Builder
1717import scala .collection .immutable .WrappedString
1818import scala .reflect .ClassTag
19+ import language .experimental .captureChecking
20+ import caps .unsafe .unsafeAssumePure
1921
2022/** Builds a collection of type `C` from elements of type `A` when a source collection of type `From` is available.
2123 * Implicit instances of `BuildFrom` are available for all collection types.
@@ -26,7 +28,11 @@ import scala.reflect.ClassTag
2628 */
2729@ implicitNotFound(msg = " Cannot construct a collection of type ${C} with elements of type ${A} based on a collection of type ${From}." )
2830trait BuildFrom [- From , - A , + C ] extends Any { self =>
29- def fromSpecific (from : From )(it : IterableOnce [A ]): C
31+ def fromSpecific (from : From )(it : IterableOnce [A ]^ ): C
32+ // !!! this is wrong, we need two versions of fromSpecific; one mapping
33+ // to C^{it} when C is an Iterable, and one mapping to C when C is a Seq, Map, or Set.
34+ // But that requires a large scale refactoring of BuildFrom. The unsafeAssumePure
35+ // calls in this file are needed to sweep that problem under the carpet.
3036
3137 /** Get a Builder for the collection. For non-strict collection types this will use an intermediate buffer.
3238 * Building collections with `fromSpecific` is preferred because it can be lazy for lazy collections. */
@@ -37,7 +43,7 @@ trait BuildFrom[-From, -A, +C] extends Any { self =>
3743
3844 /** Partially apply a BuildFrom to a Factory */
3945 def toFactory (from : From ): Factory [A , C ] = new Factory [A , C ] {
40- def fromSpecific (it : IterableOnce [A ]): C = self.fromSpecific(from)(it)
46+ def fromSpecific (it : IterableOnce [A ]^ ): C = self.fromSpecific(from)(it)
4147 def newBuilder : Builder [A , C ] = self.newBuilder(from)
4248 }
4349}
@@ -48,42 +54,42 @@ object BuildFrom extends BuildFromLowPriority1 {
4854 implicit def buildFromMapOps [CC [X , Y ] <: Map [X , Y ] with MapOps [X , Y , CC , _], K0 , V0 , K , V ]: BuildFrom [CC [K0 , V0 ] with Map [K0 , V0 ], (K , V ), CC [K , V ] with Map [K , V ]] = new BuildFrom [CC [K0 , V0 ], (K , V ), CC [K , V ]] {
4955 // TODO: Reuse a prototype instance
5056 def newBuilder (from : CC [K0 , V0 ]): Builder [(K , V ), CC [K , V ]] = (from : MapOps [K0 , V0 , CC , _]).mapFactory.newBuilder[K , V ]
51- def fromSpecific (from : CC [K0 , V0 ])(it : IterableOnce [(K , V )]): CC [K , V ] = (from : MapOps [K0 , V0 , CC , _]).mapFactory.from(it)
57+ def fromSpecific (from : CC [K0 , V0 ])(it : IterableOnce [(K , V )]^ ): CC [K , V ] = (from : MapOps [K0 , V0 , CC , _]).mapFactory.from(it)
5258 }
5359
5460 /** Build the source collection type from a SortedMapOps */
5561 implicit def buildFromSortedMapOps [CC [X , Y ] <: SortedMap [X , Y ] with SortedMapOps [X , Y , CC , _], K0 , V0 , K : Ordering , V ]: BuildFrom [CC [K0 , V0 ] with SortedMap [K0 , V0 ], (K , V ), CC [K , V ] with SortedMap [K , V ]] = new BuildFrom [CC [K0 , V0 ], (K , V ), CC [K , V ]] {
5662 def newBuilder (from : CC [K0 , V0 ]): Builder [(K , V ), CC [K , V ]] = (from : SortedMapOps [K0 , V0 , CC , _]).sortedMapFactory.newBuilder[K , V ]
57- def fromSpecific (from : CC [K0 , V0 ])(it : IterableOnce [(K , V )]): CC [K , V ] = (from : SortedMapOps [K0 , V0 , CC , _]).sortedMapFactory.from(it)
63+ def fromSpecific (from : CC [K0 , V0 ])(it : IterableOnce [(K , V )]^ ): CC [K , V ] = (from : SortedMapOps [K0 , V0 , CC , _]).sortedMapFactory.from(it)
5864 }
5965
6066 implicit def buildFromBitSet [C <: BitSet with BitSetOps [C ]]: BuildFrom [C , Int , C ] =
6167 new BuildFrom [C , Int , C ] {
62- def fromSpecific (from : C )(it : IterableOnce [Int ]): C = from.bitSetFactory.fromSpecific(it)
68+ def fromSpecific (from : C )(it : IterableOnce [Int ]^ ): C = from.bitSetFactory.fromSpecific(it)
6369 def newBuilder (from : C ): Builder [Int , C ] = from.bitSetFactory.newBuilder
6470 }
6571
6672 implicit val buildFromString : BuildFrom [String , Char , String ] =
6773 new BuildFrom [String , Char , String ] {
68- def fromSpecific (from : String )(it : IterableOnce [Char ]): String = Factory .stringFactory.fromSpecific(it)
74+ def fromSpecific (from : String )(it : IterableOnce [Char ]^ ): String = Factory .stringFactory.fromSpecific(it)
6975 def newBuilder (from : String ): Builder [Char , String ] = Factory .stringFactory.newBuilder
7076 }
7177
7278 implicit val buildFromWrappedString : BuildFrom [WrappedString , Char , WrappedString ] =
7379 new BuildFrom [WrappedString , Char , WrappedString ] {
74- def fromSpecific (from : WrappedString )(it : IterableOnce [Char ]): WrappedString = WrappedString .fromSpecific(it)
80+ def fromSpecific (from : WrappedString )(it : IterableOnce [Char ]^ ): WrappedString = WrappedString .fromSpecific(it)
7581 def newBuilder (from : WrappedString ): mutable.Builder [Char , WrappedString ] = WrappedString .newBuilder
7682 }
7783
7884 implicit def buildFromArray [A : ClassTag ]: BuildFrom [Array [_], A , Array [A ]] =
7985 new BuildFrom [Array [_], A , Array [A ]] {
80- def fromSpecific (from : Array [_])(it : IterableOnce [A ]): Array [A ] = Factory .arrayFactory[A ].fromSpecific(it)
86+ def fromSpecific (from : Array [_])(it : IterableOnce [A ]^ ): Array [A ] = Factory .arrayFactory[A ].fromSpecific(it)
8187 def newBuilder (from : Array [_]): Builder [A , Array [A ]] = Factory .arrayFactory[A ].newBuilder
8288 }
8389
8490 implicit def buildFromView [A , B ]: BuildFrom [View [A ], B , View [B ]] =
8591 new BuildFrom [View [A ], B , View [B ]] {
86- def fromSpecific (from : View [A ])(it : IterableOnce [B ]): View [B ] = View .from(it)
92+ def fromSpecific (from : View [A ])(it : IterableOnce [B ]^ ): View [B ] = View .from(it).unsafeAssumePure
8793 def newBuilder (from : View [A ]): Builder [B , View [B ]] = View .newBuilder
8894 }
8995
@@ -97,12 +103,12 @@ trait BuildFromLowPriority1 extends BuildFromLowPriority2 {
97103 // test in test/junit/scala/collection/BuildFromTest.scala and discussion in https://github.com/scala/scala/pull/10209
98104 implicit def buildFromSortedSetOps [CC [X ] <: SortedSet [X ] with SortedSetOps [X , CC , _], A0 , A : Ordering ]: BuildFrom [CC [A0 ] with SortedSet [A0 ], A , CC [A ] with SortedSet [A ]] = new BuildFrom [CC [A0 ], A , CC [A ]] {
99105 def newBuilder (from : CC [A0 ]): Builder [A , CC [A ]] = (from : SortedSetOps [A0 , CC , _]).sortedIterableFactory.newBuilder[A ]
100- def fromSpecific (from : CC [A0 ])(it : IterableOnce [A ]): CC [A ] = (from : SortedSetOps [A0 , CC , _]).sortedIterableFactory.from(it)
106+ def fromSpecific (from : CC [A0 ])(it : IterableOnce [A ]^ ): CC [A ] = (from : SortedSetOps [A0 , CC , _]).sortedIterableFactory.from(it)
101107 }
102108
103109 implicit def fallbackStringCanBuildFrom [A ]: BuildFrom [String , A , immutable.IndexedSeq [A ]] =
104110 new BuildFrom [String , A , immutable.IndexedSeq [A ]] {
105- def fromSpecific (from : String )(it : IterableOnce [A ]): immutable.IndexedSeq [A ] = immutable.IndexedSeq .from(it)
111+ def fromSpecific (from : String )(it : IterableOnce [A ]^ ): immutable.IndexedSeq [A ] = immutable.IndexedSeq .from(it)
106112 def newBuilder (from : String ): Builder [A , immutable.IndexedSeq [A ]] = immutable.IndexedSeq .newBuilder[A ]
107113 }
108114}
@@ -112,11 +118,11 @@ trait BuildFromLowPriority2 {
112118 implicit def buildFromIterableOps [CC [X ] <: Iterable [X ] with IterableOps [X , CC , _], A0 , A ]: BuildFrom [CC [A0 ], A , CC [A ]] = new BuildFrom [CC [A0 ], A , CC [A ]] {
113119 // TODO: Reuse a prototype instance
114120 def newBuilder (from : CC [A0 ]): Builder [A , CC [A ]] = (from : IterableOps [A0 , CC , _]).iterableFactory.newBuilder[A ]
115- def fromSpecific (from : CC [A0 ])(it : IterableOnce [A ]): CC [A ] = (from : IterableOps [A0 , CC , _]).iterableFactory.from(it)
121+ def fromSpecific (from : CC [A0 ])(it : IterableOnce [A ]^ ): CC [A ] = (from : IterableOps [A0 , CC , _]).iterableFactory.from(it).unsafeAssumePure
116122 }
117123
118124 implicit def buildFromIterator [A ]: BuildFrom [Iterator [_], A , Iterator [A ]] = new BuildFrom [Iterator [_], A , Iterator [A ]] {
119125 def newBuilder (from : Iterator [_]): mutable.Builder [A , Iterator [A ]] = Iterator .newBuilder
120- def fromSpecific (from : Iterator [_])(it : IterableOnce [A ]): Iterator [A ] = Iterator .from(it)
126+ def fromSpecific (from : Iterator [_])(it : IterableOnce [A ]^ ): Iterator [A ] = Iterator .from(it).unsafeAssumePure
121127 }
122128}
0 commit comments