Skip to content

Commit

Permalink
Drop FreeSeqFactory from stdlib-cc (#19849)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linyxus authored Mar 2, 2024
2 parents 2cd5721 + 4464a73 commit c7a0459
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 12 deletions.
7 changes: 1 addition & 6 deletions scala2-library-cc/src/scala/collection/Factory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -296,15 +296,10 @@ object IterableFactory {
}
}

// !!! Needed to add this separate trait
trait FreeSeqFactory[+CC[A]] extends IterableFactory[CC]:
def from[A](source: IterableOnce[A]^): CC[A]
override def apply[A](elems: A*): CC[A] = from(elems)

/**
* @tparam CC Collection type constructor (e.g. `List`)
*/
trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends FreeSeqFactory[CC] {
trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends IterableFactory[CC] {
import SeqFactory.UnapplySeqWrapper
final def unapplySeq[A](x: CC[A] @uncheckedVariance): UnapplySeqWrapper[A] = new UnapplySeqWrapper(x) // TODO is uncheckedVariance sound here?
}
Expand Down
8 changes: 4 additions & 4 deletions scala2-library-cc/src/scala/collection/Seq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self =>

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

def iterableFactory: FreeSeqFactory[CC]

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

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

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

/** Iterates over distinct permutations of elements.
*
Expand Down Expand Up @@ -947,7 +946,8 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self =>
*/
def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] =
iterableFactory.from(new View.Patched(this, from, other, replaced))

.unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq

/** A copy of this $coll with one single replaced element.
* @param index the position of the replacement
* @param elem the replacing element
Expand Down
4 changes: 2 additions & 2 deletions scala2-library-cc/src/scala/collection/generic/IsSeq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ object IsSeq {
def toIterable: Iterable[Char] = new immutable.WrappedString(s)
protected[this] def coll: String = s
protected[this] def fromSpecific(coll: IterableOnce[Char]^): String = coll.iterator.mkString
def iterableFactory: FreeSeqFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged
def iterableFactory: IterableFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged
override def empty: String = ""
protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder
def iterator: Iterator[Char] = s.iterator
Expand All @@ -102,7 +102,7 @@ object IsSeq {
def toIterable: Iterable[A] = mutable.ArraySeq.make[A](a)
protected def coll: Array[A] = a
protected def fromSpecific(coll: IterableOnce[A]^): Array[A] = Array.from(coll)
def iterableFactory: FreeSeqFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged
def iterableFactory: IterableFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged
override def empty: Array[A] = Array.empty[A]
protected def newSpecificBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder
def iterator: Iterator[A] = a.iterator
Expand Down

0 comments on commit c7a0459

Please sign in to comment.