@@ -22,11 +22,19 @@ trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterabl
2222 final def toIterable : this .type = this
2323
2424 // TODO scalac generates an override for this in AbstractMap; Making it final leads to a VerifyError
25- protected [ this ] def coll : this .type = this
25+ protected def coll : this .type = this
2626
27- protected [ this ] def fromSpecificIterable (coll : Iterable [A ]): IterableCC [A ] = iterableFactory.from(coll)
28- protected [ this ] def newSpecificBuilder (): Builder [A , IterableCC [A ]] = iterableFactory.newBuilder[A ]()
27+ protected def fromSpecificIterable (coll : Iterable [A @ uncheckedVariance ]): IterableCC [A ] @ uncheckedVariance = iterableFactory.from(coll)
28+ protected def newSpecificBuilder (): Builder [A , IterableCC [A ]] @ uncheckedVariance = iterableFactory.newBuilder[A ]()
2929
30+ /**
31+ * @note This operation '''has''' to be overridden by concrete collection classes to effectively
32+ * return an `IterableFactory[IterableCC]`. The implementation in `Iterable` only returns
33+ * an `IterableFactory[Iterable]`, but the compiler will '''not''' throw an error if the
34+ * effective `IterableCC` type constructor is more specific than `Iterable`.
35+ *
36+ * @return The factory of this collection.
37+ */
3038 def iterableFactory : IterableFactory [IterableCC ] = Iterable
3139}
3240
@@ -66,7 +74,14 @@ trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterabl
6674 */
6775trait IterableOps [+ A , + CC [_], + C ] extends Any with IterableOnce [A ] with IterableOnceOps [A , CC , C ] {
6876
69- protected [this ] type IterableCC [X ] = CC [X ]
77+ /**
78+ * Type alias to `CC`. It is used to provide a default implementation of the `fromSpecificIterable`
79+ * and `newSpecificBuilder` operations.
80+ *
81+ * Due to the `@uncheckedVariance` annotation, usage of this type member can be unsound and is
82+ * therefore not recommended.
83+ */
84+ protected type IterableCC [X ] = CC [X ] @ uncheckedVariance
7085
7186 /**
7287 * @return This collection as an `Iterable[A]`. No new collection will be built if `this` is already an `Iterable[A]`.
@@ -76,21 +91,26 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
7691 /**
7792 * @return This collection as a `C`.
7893 */
79- protected [ this ] def coll : C
94+ protected def coll : C
8095
8196 /**
8297 * Defines how to turn a given `Iterable[A]` into a collection of type `C`.
8398 *
8499 * This process can be done in a strict way or a non-strict way (ie. without evaluating
85100 * the elements of the resulting collections). In other words, this methods defines
86101 * the evaluation model of the collection.
102+ *
103+ * @note As witnessed by the `@uncheckedVariance` annotation, using this method
104+ * might be unsound. However, as long as it is called with an
105+ * `Iterable[A]` obtained from `this` collection (as it is the case in the
106+ * implementations of operations where we use a `View[A]`), it is safe.
87107 */
88- protected [ this ] def fromSpecificIterable (coll : Iterable [A ]): C
108+ protected def fromSpecificIterable (coll : Iterable [A @ uncheckedVariance ]): C
89109
90110 /** Similar to `fromSpecificIterable`, but for a (possibly) different type of element.
91111 * Note that the return type is now `CC[E]`.
92112 */
93- @ `inline` final protected [ this ] def fromIterable [E ](it : Iterable [E ]): CC [E ] = iterableFactory.from(it)
113+ @ `inline` final protected def fromIterable [E ](it : Iterable [E ]): CC [E ] = iterableFactory.from(it)
94114
95115 /**
96116 * @return The companion object of this ${coll}, providing various factory methods.
@@ -104,8 +124,12 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
104124 * it is possible to implement this method but the resulting `Builder` will break laziness.
105125 * As a consequence, operations should preferably be implemented with `fromSpecificIterable`
106126 * instead of this method.
127+ *
128+ * @note As witnessed by the `@uncheckedVariance` annotation, using this method might
129+ * be unsound. However, as long as the returned builder is only fed
130+ * with `A` values taken from `this` instance, it is safe.
107131 */
108- protected [ this ] def newSpecificBuilder (): Builder [A , C ]
132+ protected def newSpecificBuilder (): Builder [A @ uncheckedVariance , C ]
109133
110134 /** Selects the first element of this $coll.
111135 * $orderDependent
@@ -315,26 +339,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
315339 * All these operations apply to those elements of this $coll
316340 * which satisfy the predicate `p`.
317341 */
318- def withFilter (p : A => Boolean ): collection.WithFilter [A , CC ] = new WithFilter (p)
319-
320- /** A template trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods
321- * of trait `Iterable`.
322- *
323- * @define coll iterable collection
324- */
325- class WithFilter (p : A => Boolean ) extends collection.WithFilter [A , CC ] {
326-
327- protected [this ] def filtered = new View .Filter (IterableOps .this , p, isFlipped = false )
328-
329- def map [B ](f : A => B ): CC [B ] = iterableFactory.from(new View .Map (filtered, f))
330-
331- def flatMap [B ](f : A => IterableOnce [B ]): CC [B ] = iterableFactory.from(new View .FlatMap (filtered, f))
332-
333- def foreach [U ](f : A => U ): Unit = filtered.foreach(f)
334-
335- def withFilter (q : A => Boolean ): WithFilter = new WithFilter (a => p(a) && q(a))
336-
337- }
342+ def withFilter (p : A => Boolean ): collection.WithFilter [A , CC ] = new IterableOps .WithFilter (this , p)
338343
339344 /** A pair of, first, all elements that satisfy prediacte `p` and, second,
340345 * all elements that do not. Interesting because it splits a collection in two.
@@ -710,6 +715,39 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
710715 }
711716}
712717
718+ object IterableOps {
719+
720+ /** A trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods
721+ * of trait `Iterable`.
722+ *
723+ * @tparam A Element type (e.g. `Int`)
724+ * @tparam CC Collection type constructor (e.g. `List`)
725+ *
726+ * @define coll collection
727+ */
728+ class WithFilter [+ A , + CC [_]](
729+ self : IterableOps [A , CC , _],
730+ p : A => Boolean
731+ ) extends collection.WithFilter [A , CC ] {
732+
733+ protected def filtered : Iterable [A ] =
734+ new View .Filter (self, p, isFlipped = false )
735+
736+ def map [B ](f : A => B ): CC [B ] =
737+ self.iterableFactory.from(new View .Map (filtered, f))
738+
739+ def flatMap [B ](f : A => IterableOnce [B ]): CC [B ] =
740+ self.iterableFactory.from(new View .FlatMap (filtered, f))
741+
742+ def foreach [U ](f : A => U ): Unit = filtered.foreach(f)
743+
744+ def withFilter (q : A => Boolean ): WithFilter [A , CC ] =
745+ new WithFilter (self, (a : A ) => p(a) && q(a))
746+
747+ }
748+
749+ }
750+
713751object Iterable extends IterableFactory .Delegate [Iterable ](immutable.Iterable ) {
714752 implicit def toLazyZipOps [A , CC [X ] <: Iterable [X ]](that : CC [A ]): LazyZipOps [A , CC [A ]] = new LazyZipOps (that)
715753}
0 commit comments