Skip to content

Commit c7a0459

Browse files
authored
Drop FreeSeqFactory from stdlib-cc (#19849)
FreeSeqFactory was a construction to demonstrate type safety for certain iterableFactory.from calls where we rely in the fact that for all Seqs iterableFactory has an eager implementation of from. While that shows that we _can_ make it typesafe, it does not work at runtime as a drop-in replacement for stdlib since of course stdlib does not have a FreeSeqFactory. This commit drops FreeSeqFactory and adds three unsafeAssumePure calls instead, with explanations. Fixes #19845
2 parents 2cd5721 + 4464a73 commit c7a0459

File tree

3 files changed

+7
-12
lines changed

3 files changed

+7
-12
lines changed

Diff for: scala2-library-cc/src/scala/collection/Factory.scala

+1-6
Original file line numberDiff line numberDiff line change
@@ -296,15 +296,10 @@ object IterableFactory {
296296
}
297297
}
298298

299-
// !!! Needed to add this separate trait
300-
trait FreeSeqFactory[+CC[A]] extends IterableFactory[CC]:
301-
def from[A](source: IterableOnce[A]^): CC[A]
302-
override def apply[A](elems: A*): CC[A] = from(elems)
303-
304299
/**
305300
* @tparam CC Collection type constructor (e.g. `List`)
306301
*/
307-
trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends FreeSeqFactory[CC] {
302+
trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends IterableFactory[CC] {
308303
import SeqFactory.UnapplySeqWrapper
309304
final def unapplySeq[A](x: CC[A] @uncheckedVariance): UnapplySeqWrapper[A] = new UnapplySeqWrapper(x) // TODO is uncheckedVariance sound here?
310305
}

Diff for: scala2-library-cc/src/scala/collection/Seq.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self =>
8181

8282
override def view: SeqView[A] = new SeqView.Id[A](this)
8383

84-
def iterableFactory: FreeSeqFactory[CC]
85-
8684
/** Get the element at the specified index. This operation is provided for convenience in `Seq`. It should
8785
* not be assumed to be efficient unless you have an `IndexedSeq`. */
8886
@throws[IndexOutOfBoundsException]
@@ -167,7 +165,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self =>
167165
def prependedAll[B >: A](prefix: IterableOnce[B]^): CC[B] = iterableFactory.from(prefix match {
168166
case prefix: Iterable[B] => new View.Concat(prefix, this)
169167
case _ => prefix.iterator ++ iterator
170-
})
168+
}).unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq
171169

172170
/** Alias for `prependedAll` */
173171
@`inline` override final def ++: [B >: A](prefix: IterableOnce[B]^): CC[B] = prependedAll(prefix)
@@ -532,6 +530,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self =>
532530

533531
@deprecated("Use .reverseIterator.map(f).to(...) instead of .reverseMap(f)", "2.13.0")
534532
def reverseMap[B](f: A => B): CC[B] = iterableFactory.from(new View.Map(View.fromIteratorProvider(() => reverseIterator), f))
533+
.unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq
535534

536535
/** Iterates over distinct permutations of elements.
537536
*
@@ -947,7 +946,8 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self =>
947946
*/
948947
def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] =
949948
iterableFactory.from(new View.Patched(this, from, other, replaced))
950-
949+
.unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq
950+
951951
/** A copy of this $coll with one single replaced element.
952952
* @param index the position of the replacement
953953
* @param elem the replacing element

Diff for: scala2-library-cc/src/scala/collection/generic/IsSeq.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ object IsSeq {
8484
def toIterable: Iterable[Char] = new immutable.WrappedString(s)
8585
protected[this] def coll: String = s
8686
protected[this] def fromSpecific(coll: IterableOnce[Char]^): String = coll.iterator.mkString
87-
def iterableFactory: FreeSeqFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged
87+
def iterableFactory: IterableFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged
8888
override def empty: String = ""
8989
protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder
9090
def iterator: Iterator[Char] = s.iterator
@@ -102,7 +102,7 @@ object IsSeq {
102102
def toIterable: Iterable[A] = mutable.ArraySeq.make[A](a)
103103
protected def coll: Array[A] = a
104104
protected def fromSpecific(coll: IterableOnce[A]^): Array[A] = Array.from(coll)
105-
def iterableFactory: FreeSeqFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged
105+
def iterableFactory: IterableFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged
106106
override def empty: Array[A] = Array.empty[A]
107107
protected def newSpecificBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder
108108
def iterator: Iterator[A] = a.iterator

0 commit comments

Comments
 (0)