diff --git a/scala2-library-cc/src/scala/collection/ArrayOps.scala b/scala2-library-cc/src/scala/collection/ArrayOps.scala index b2ed04d02de7..e8548c12751f 100644 --- a/scala2-library-cc/src/scala/collection/ArrayOps.scala +++ b/scala2-library-cc/src/scala/collection/ArrayOps.scala @@ -15,6 +15,7 @@ package collection import java.lang.Math.{max, min} import java.util.Arrays +import language.experimental.captureChecking import scala.Predef.{ // unimport all array-related implicit conversions to avoid triggering them accidentally genericArrayOps => _, @@ -116,7 +117,7 @@ object ArrayOps { flatMap[B](x => asIterable(f(x))) /** Creates a new non-strict filter which combines this filter with the given predicate. */ - def withFilter(q: A => Boolean): WithFilter[A] = new WithFilter[A](a => p(a) && q(a), xs) + def withFilter(q: A => Boolean): WithFilter[A]^{this, q} = new WithFilter[A](a => p(a) && q(a), xs) } @SerialVersionUID(3L) @@ -366,7 +367,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { def inits: Iterator[Array[A]] = iterateUntilEmpty(xs => new ArrayOps(xs).init) // A helper for tails and inits. - private[this] def iterateUntilEmpty(f: Array[A] => Array[A]): Iterator[Array[A]] = + private[this] def iterateUntilEmpty(f: Array[A] => Array[A]): Iterator[Array[A]]^{f} = Iterator.iterate(xs)(f).takeWhile(x => x.length != 0) ++ Iterator.single(Array.empty[A]) /** An array containing the first `n` elements of this array. */ @@ -663,7 +664,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * All these operations apply to those elements of this array * which satisfy the predicate `p`. */ - def withFilter(p: A => Boolean): ArrayOps.WithFilter[A] = new ArrayOps.WithFilter[A](p, xs) + def withFilter(p: A => Boolean): ArrayOps.WithFilter[A]^{p} = new ArrayOps.WithFilter[A](p, xs) /** Finds index of first occurrence of some value in this array after or at some start index. * @@ -1345,7 +1346,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @tparam B the type of the elements after being transformed by `f` * @return a new array consisting of all the elements of this array without duplicates. */ - def distinctBy[B](f: A => B): Array[A] = + def distinctBy[B](f: A -> B): Array[A] = ArrayBuilder.make[A].addAll(iterator.distinctBy(f)).result() /** A copy of this array with an element value appended until a given target length is reached. diff --git a/scala2-library-cc/src/scala/collection/BitSet.scala b/scala2-library-cc/src/scala/collection/BitSet.scala index e8ca89806455..39c15dbe808f 100644 --- a/scala2-library-cc/src/scala/collection/BitSet.scala +++ b/scala2-library-cc/src/scala/collection/BitSet.scala @@ -18,7 +18,7 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.annotation.nowarn import scala.collection.Stepper.EfficientSplit import scala.collection.mutable.Builder - +import language.experimental.captureChecking /** Base type of bitsets. * @@ -33,7 +33,7 @@ import scala.collection.mutable.Builder * @define Coll `BitSet` */ trait BitSet extends SortedSet[Int] with BitSetOps[BitSet] { - override protected def fromSpecific(coll: IterableOnce[Int]): BitSet = bitSetFactory.fromSpecific(coll) + override protected def fromSpecific(coll: IterableOnce[Int]^): BitSet = bitSetFactory.fromSpecific(coll) override protected def newSpecificBuilder: Builder[Int, BitSet] = bitSetFactory.newBuilder override def empty: BitSet = bitSetFactory.empty @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") @@ -48,7 +48,7 @@ object BitSet extends SpecificIterableFactory[Int, BitSet] { def empty: BitSet = immutable.BitSet.empty def newBuilder: Builder[Int, BitSet] = immutable.BitSet.newBuilder - def fromSpecific(it: IterableOnce[Int]): BitSet = immutable.BitSet.fromSpecific(it) + def fromSpecific(it: IterableOnce[Int]^): BitSet = immutable.BitSet.fromSpecific(it) @SerialVersionUID(3L) private[collection] abstract class SerializationProxy(@transient protected val coll: BitSet) extends Serializable { diff --git a/scala2-library-cc/src/scala/collection/BufferedIterator.scala b/scala2-library-cc/src/scala/collection/BufferedIterator.scala index bc35ee0a25da..cca40dd31d40 100644 --- a/scala2-library-cc/src/scala/collection/BufferedIterator.scala +++ b/scala2-library-cc/src/scala/collection/BufferedIterator.scala @@ -11,7 +11,7 @@ */ package scala.collection - +import language.experimental.captureChecking /** Buffered iterators are iterators which provide a method `head` * that inspects the next element without discarding it. diff --git a/scala2-library-cc/src/scala/collection/BuildFrom.scala b/scala2-library-cc/src/scala/collection/BuildFrom.scala index bc9c49d9493c..d82e90777d3e 100644 --- a/scala2-library-cc/src/scala/collection/BuildFrom.scala +++ b/scala2-library-cc/src/scala/collection/BuildFrom.scala @@ -16,6 +16,8 @@ import scala.annotation.implicitNotFound import scala.collection.mutable.Builder import scala.collection.immutable.WrappedString import scala.reflect.ClassTag +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure /** 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. @@ -26,7 +28,11 @@ import scala.reflect.ClassTag */ @implicitNotFound(msg = "Cannot construct a collection of type ${C} with elements of type ${A} based on a collection of type ${From}.") trait BuildFrom[-From, -A, +C] extends Any { self => - def fromSpecific(from: From)(it: IterableOnce[A]): C + def fromSpecific(from: From)(it: IterableOnce[A]^): C + // !!! this is wrong, we need two versions of fromSpecific; one mapping + // to C^{it} when C is an Iterable, and one mapping to C when C is a Seq, Map, or Set. + // But that requires a large scale refactoring of BuildFrom. The unsafeAssumePure + // calls in this file are needed to sweep that problem under the carpet. /** Get a Builder for the collection. For non-strict collection types this will use an intermediate buffer. * 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 => /** Partially apply a BuildFrom to a Factory */ def toFactory(from: From): Factory[A, C] = new Factory[A, C] { - def fromSpecific(it: IterableOnce[A]): C = self.fromSpecific(from)(it) + def fromSpecific(it: IterableOnce[A]^): C = self.fromSpecific(from)(it) def newBuilder: Builder[A, C] = self.newBuilder(from) } } @@ -48,42 +54,42 @@ object BuildFrom extends BuildFromLowPriority1 { 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]] { //TODO: Reuse a prototype instance def newBuilder(from: CC[K0, V0]): Builder[(K, V), CC[K, V]] = (from: MapOps[K0, V0, CC, _]).mapFactory.newBuilder[K, V] - def fromSpecific(from: CC[K0, V0])(it: IterableOnce[(K, V)]): CC[K, V] = (from: MapOps[K0, V0, CC, _]).mapFactory.from(it) + def fromSpecific(from: CC[K0, V0])(it: IterableOnce[(K, V)]^): CC[K, V] = (from: MapOps[K0, V0, CC, _]).mapFactory.from(it) } /** Build the source collection type from a SortedMapOps */ 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]] { def newBuilder(from: CC[K0, V0]): Builder[(K, V), CC[K, V]] = (from: SortedMapOps[K0, V0, CC, _]).sortedMapFactory.newBuilder[K, V] - def fromSpecific(from: CC[K0, V0])(it: IterableOnce[(K, V)]): CC[K, V] = (from: SortedMapOps[K0, V0, CC, _]).sortedMapFactory.from(it) + def fromSpecific(from: CC[K0, V0])(it: IterableOnce[(K, V)]^): CC[K, V] = (from: SortedMapOps[K0, V0, CC, _]).sortedMapFactory.from(it) } implicit def buildFromBitSet[C <: BitSet with BitSetOps[C]]: BuildFrom[C, Int, C] = new BuildFrom[C, Int, C] { - def fromSpecific(from: C)(it: IterableOnce[Int]): C = from.bitSetFactory.fromSpecific(it) + def fromSpecific(from: C)(it: IterableOnce[Int]^): C = from.bitSetFactory.fromSpecific(it) def newBuilder(from: C): Builder[Int, C] = from.bitSetFactory.newBuilder } implicit val buildFromString: BuildFrom[String, Char, String] = new BuildFrom[String, Char, String] { - def fromSpecific(from: String)(it: IterableOnce[Char]): String = Factory.stringFactory.fromSpecific(it) + def fromSpecific(from: String)(it: IterableOnce[Char]^): String = Factory.stringFactory.fromSpecific(it) def newBuilder(from: String): Builder[Char, String] = Factory.stringFactory.newBuilder } implicit val buildFromWrappedString: BuildFrom[WrappedString, Char, WrappedString] = new BuildFrom[WrappedString, Char, WrappedString] { - def fromSpecific(from: WrappedString)(it: IterableOnce[Char]): WrappedString = WrappedString.fromSpecific(it) + def fromSpecific(from: WrappedString)(it: IterableOnce[Char]^): WrappedString = WrappedString.fromSpecific(it) def newBuilder(from: WrappedString): mutable.Builder[Char, WrappedString] = WrappedString.newBuilder } implicit def buildFromArray[A : ClassTag]: BuildFrom[Array[_], A, Array[A]] = new BuildFrom[Array[_], A, Array[A]] { - def fromSpecific(from: Array[_])(it: IterableOnce[A]): Array[A] = Factory.arrayFactory[A].fromSpecific(it) + def fromSpecific(from: Array[_])(it: IterableOnce[A]^): Array[A] = Factory.arrayFactory[A].fromSpecific(it) def newBuilder(from: Array[_]): Builder[A, Array[A]] = Factory.arrayFactory[A].newBuilder } 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] = View.from(it) + def fromSpecific(from: View[A])(it: IterableOnce[B]^): View[B] = View.from(it).unsafeAssumePure def newBuilder(from: View[A]): Builder[B, View[B]] = View.newBuilder } @@ -97,12 +103,12 @@ trait BuildFromLowPriority1 extends BuildFromLowPriority2 { // test in test/junit/scala/collection/BuildFromTest.scala and discussion in https://github.com/scala/scala/pull/10209 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]] { def newBuilder(from: CC[A0]): Builder[A, CC[A]] = (from: SortedSetOps[A0, CC, _]).sortedIterableFactory.newBuilder[A] - def fromSpecific(from: CC[A0])(it: IterableOnce[A]): CC[A] = (from: SortedSetOps[A0, CC, _]).sortedIterableFactory.from(it) + def fromSpecific(from: CC[A0])(it: IterableOnce[A]^): CC[A] = (from: SortedSetOps[A0, CC, _]).sortedIterableFactory.from(it) } implicit def fallbackStringCanBuildFrom[A]: BuildFrom[String, A, immutable.IndexedSeq[A]] = new BuildFrom[String, A, immutable.IndexedSeq[A]] { - def fromSpecific(from: String)(it: IterableOnce[A]): immutable.IndexedSeq[A] = immutable.IndexedSeq.from(it) + def fromSpecific(from: String)(it: IterableOnce[A]^): immutable.IndexedSeq[A] = immutable.IndexedSeq.from(it) def newBuilder(from: String): Builder[A, immutable.IndexedSeq[A]] = immutable.IndexedSeq.newBuilder[A] } } @@ -112,11 +118,11 @@ trait BuildFromLowPriority2 { 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]] { //TODO: Reuse a prototype instance def newBuilder(from: CC[A0]): Builder[A, CC[A]] = (from: IterableOps[A0, CC, _]).iterableFactory.newBuilder[A] - def fromSpecific(from: CC[A0])(it: IterableOnce[A]): CC[A] = (from: IterableOps[A0, CC, _]).iterableFactory.from(it) + def fromSpecific(from: CC[A0])(it: IterableOnce[A]^): CC[A] = (from: IterableOps[A0, CC, _]).iterableFactory.from(it).unsafeAssumePure } implicit def buildFromIterator[A]: BuildFrom[Iterator[_], A, Iterator[A]] = new BuildFrom[Iterator[_], A, Iterator[A]] { def newBuilder(from: Iterator[_]): mutable.Builder[A, Iterator[A]] = Iterator.newBuilder - def fromSpecific(from: Iterator[_])(it: IterableOnce[A]): Iterator[A] = Iterator.from(it) + def fromSpecific(from: Iterator[_])(it: IterableOnce[A]^): Iterator[A] = Iterator.from(it).unsafeAssumePure } } diff --git a/scala2-library-cc/src/scala/collection/DefaultMap.scala b/scala2-library-cc/src/scala/collection/DefaultMap.scala index cbc61d8c0268..baa9eceadae5 100644 --- a/scala2-library-cc/src/scala/collection/DefaultMap.scala +++ b/scala2-library-cc/src/scala/collection/DefaultMap.scala @@ -12,7 +12,7 @@ package scala package collection - +import language.experimental.captureChecking /** A default map which builds a default `immutable.Map` implementation for all * transformations. diff --git a/scala2-library-cc/src/scala/collection/Factory.scala b/scala2-library-cc/src/scala/collection/Factory.scala index 2b15f1cc15d1..c50fa395a0fb 100644 --- a/scala2-library-cc/src/scala/collection/Factory.scala +++ b/scala2-library-cc/src/scala/collection/Factory.scala @@ -18,6 +18,8 @@ import scala.language.implicitConversions import scala.collection.mutable.Builder import scala.annotation.unchecked.uncheckedVariance import scala.reflect.ClassTag +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure /** * A factory that builds a collection of type `C` with elements of type `A`. @@ -29,14 +31,14 @@ import scala.reflect.ClassTag * @tparam A Type of elements (e.g. `Int`, `Boolean`, etc.) * @tparam C Type of collection (e.g. `List[Int]`, `TreeMap[Int, String]`, etc.) */ -trait Factory[-A, +C] extends Any { +trait Factory[-A, +C] extends Pure { /** * @return A collection of type `C` containing the same elements * as the source collection `it`. * @param it Source collection */ - def fromSpecific(it: IterableOnce[A]): C + def fromSpecific(it: IterableOnce[A]^): C /** Get a Builder for the collection. For non-strict collection types this will use an intermediate buffer. * Building collections with `fromSpecific` is preferred because it can be lazy for lazy collections. */ @@ -48,7 +50,7 @@ object Factory { implicit val stringFactory: Factory[Char, String] = new StringFactory @SerialVersionUID(3L) private class StringFactory extends Factory[Char, String] with Serializable { - def fromSpecific(it: IterableOnce[Char]): String = { + def fromSpecific(it: IterableOnce[Char]^): String = { val b = new mutable.StringBuilder(scala.math.max(0, it.knownSize)) b ++= it b.result() @@ -59,7 +61,7 @@ object Factory { implicit def arrayFactory[A: ClassTag]: Factory[A, Array[A]] = new ArrayFactory[A] @SerialVersionUID(3L) private class ArrayFactory[A: ClassTag] extends Factory[A, Array[A]] with Serializable { - def fromSpecific(it: IterableOnce[A]): Array[A] = { + def fromSpecific(it: IterableOnce[A]^): Array[A] = { val b = newBuilder b.sizeHint(scala.math.max(0, it.knownSize)) b ++= it @@ -80,7 +82,7 @@ object Factory { * @define coll collection * @define Coll `Iterable` */ -trait IterableFactory[+CC[_]] extends Serializable { +trait IterableFactory[+CC[_]] extends Serializable, Pure { /** Creates a target $coll from an existing source collection * @@ -88,7 +90,7 @@ trait IterableFactory[+CC[_]] extends Serializable { * @tparam A the type of the collection’s elements * @return a new $coll with the elements of `source` */ - def from[A](source: IterableOnce[A]): CC[A] + def from[A](source: IterableOnce[A]^): CC[A]^{source} /** An empty collection * @tparam A the type of the ${coll}'s elements @@ -109,7 +111,7 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param f the function that's repeatedly applied * @return a $coll with `len` values in the sequence `start, f(start), f(f(start)), ...` */ - def iterate[A](start: A, len: Int)(f: A => A): CC[A] = from(new View.Iterate(start, len)(f)) + def iterate[A](start: A, len: Int)(f: A => A): CC[A]^{f} = from(new View.Iterate(start, len)(f)) /** Produces a $coll that uses a function `f` to produce elements of type `A` * and update an internal state of type `S`. @@ -121,7 +123,7 @@ trait IterableFactory[+CC[_]] extends Serializable { * @tparam S Type of the internal state * @return a $coll that produces elements using `f` until `f` returns `None` */ - def unfold[A, S](init: S)(f: S => Option[(A, S)]): CC[A] = from(new View.Unfold(init)(f)) + def unfold[A, S](init: S)(f: S => Option[(A, S)]): CC[A]^{f} = from(new View.Unfold(init)(f)) /** Produces a $coll containing a sequence of increasing of integers. * @@ -150,7 +152,7 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param elem the element computation * @return A $coll that contains the results of `n` evaluations of `elem`. */ - def fill[A](n: Int)(elem: => A): CC[A] = from(new View.Fill(n)(elem)) + def fill[A](n: Int)(elem: => A): CC[A]^{elem} = from(new View.Fill(n)(elem)) /** Produces a two-dimensional $coll containing the results of some element computation a number of times. * @param n1 the number of elements in the 1st dimension @@ -158,7 +160,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param elem the element computation * @return A $coll that contains the results of `n1 x n2` evaluations of `elem`. */ - def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A] @uncheckedVariance] = fill(n1)(fill(n2)(elem)) + def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A] @uncheckedVariance]^{elem} = // !!! problem with checking rhs under cc + ??? // fill(n1)(fill(n2)(elem)) /** Produces a three-dimensional $coll containing the results of some element computation a number of times. * @param n1 the number of elements in the 1st dimension @@ -167,7 +170,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param elem the element computation * @return A $coll that contains the results of `n1 x n2 x n3` evaluations of `elem`. */ - def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]] @uncheckedVariance] = fill(n1)(fill(n2, n3)(elem)) + def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]] @uncheckedVariance]^{elem} = // !!! problem with checking rhs under cc + ??? // fill(n1)(fill(n2, n3)(elem)).unsafeAssumePure /** Produces a four-dimensional $coll containing the results of some element computation a number of times. * @param n1 the number of elements in the 1st dimension @@ -177,8 +181,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param elem the element computation * @return A $coll that contains the results of `n1 x n2 x n3 x n4` evaluations of `elem`. */ - def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]] @uncheckedVariance] = - fill(n1)(fill(n2, n3, n4)(elem)) + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]] @uncheckedVariance]^{elem} = // !!! problem with checking rhs under cc + ??? // fill(n1)(fill(n2, n3, n4)(elem)) /** Produces a five-dimensional $coll containing the results of some element computation a number of times. * @param n1 the number of elements in the 1st dimension @@ -189,15 +193,15 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param elem the element computation * @return A $coll that contains the results of `n1 x n2 x n3 x n4 x n5` evaluations of `elem`. */ - def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]] @uncheckedVariance] = - fill(n1)(fill(n2, n3, n4, n5)(elem)) + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]] @uncheckedVariance]^{elem} = // !!! problem with checking rhs under cc + ??? // fill(n1)(fill(n2, n3, n4, n5)(elem)) /** Produces a $coll containing values of a given function over a range of integer values starting from 0. * @param n The number of elements in the $coll * @param f The function computing element values * @return A $coll consisting of elements `f(0), ..., f(n -1)` */ - def tabulate[A](n: Int)(f: Int => A): CC[A] = from(new View.Tabulate(n)(f)) + def tabulate[A](n: Int)(f: Int => A): CC[A]^{f} = from(new View.Tabulate(n)(f)) /** Produces a two-dimensional $coll containing values of a given function over ranges of integer values starting from 0. * @param n1 the number of elements in the 1st dimension @@ -206,8 +210,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @return A $coll consisting of elements `f(i1, i2)` * for `0 <= i1 < n1` and `0 <= i2 < n2`. */ - def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A] @uncheckedVariance] = - tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) + def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A] @uncheckedVariance]^{f} = // !!! problem with checking rhs under cc + ??? // tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) /** Produces a three-dimensional $coll containing values of a given function over ranges of integer values starting from 0. * @param n1 the number of elements in the 1st dimension @@ -217,8 +221,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @return A $coll consisting of elements `f(i1, i2, i3)` * for `0 <= i1 < n1`, `0 <= i2 < n2`, and `0 <= i3 < n3`. */ - def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]] @uncheckedVariance] = - tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) + def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]] @uncheckedVariance]^{f} = // !!! problem with checking rhs under cc + ??? // tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) /** Produces a four-dimensional $coll containing values of a given function over ranges of integer values starting from 0. * @param n1 the number of elements in the 1st dimension @@ -229,8 +233,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @return A $coll consisting of elements `f(i1, i2, i3, i4)` * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, and `0 <= i4 < n4`. */ - def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]] @uncheckedVariance] = - tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]] @uncheckedVariance]^{f} = // !!! problem with checking rhs under cc + ??? // tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) /** Produces a five-dimensional $coll containing values of a given function over ranges of integer values starting from 0. * @param n1 the number of elements in the 1st dimension @@ -242,8 +246,8 @@ trait IterableFactory[+CC[_]] extends Serializable { * @return A $coll consisting of elements `f(i1, i2, i3, i4, i5)` * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, `0 <= i4 < n4`, and `0 <= i5 < n5`. */ - def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]] @uncheckedVariance] = - tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]] @uncheckedVariance]^{f} = // !!! problem with checking rhs under cc + ??? // tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) /** Concatenates all argument collections into a single $coll. * @@ -271,13 +275,15 @@ object IterableFactory { @SerialVersionUID(3L) private[this] class ToFactory[A, CC[_]](factory: IterableFactory[CC]) extends Factory[A, CC[A]] with Serializable { - def fromSpecific(it: IterableOnce[A]): CC[A] = factory.from[A](it) + def fromSpecific(it: IterableOnce[A]^): CC[A] = factory.from[A](it).unsafeAssumePure + // unsafeAssumePure needed but is unsound, since we confuse Seq and Iterable fromSpecific def newBuilder: Builder[A, CC[A]] = factory.newBuilder[A] } implicit def toBuildFrom[A, CC[_]](factory: IterableFactory[CC]): BuildFrom[Any, A, CC[A]] = new BuildFrom[Any, A, CC[A]] { - def fromSpecific(from: Any)(it: IterableOnce[A]) = factory.from(it) + def fromSpecific(from: Any)(it: IterableOnce[A]^): CC[A] = + factory.from(it).unsafeAssumePure // !!! see remark in BuildFrom why this is necessary def newBuilder(from: Any) = factory.newBuilder } @@ -285,15 +291,20 @@ object IterableFactory { class Delegate[CC[_]](delegate: IterableFactory[CC]) extends IterableFactory[CC] { override def apply[A](elems: A*): CC[A] = delegate.apply(elems: _*) def empty[A]: CC[A] = delegate.empty - def from[E](it: IterableOnce[E]): CC[E] = delegate.from(it) + def from[E](it: IterableOnce[E]^): CC[E]^{it} = delegate.from(it) def newBuilder[A]: Builder[A, CC[A]] = delegate.newBuilder[A] } } +// !!! 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 IterableFactory[CC] { +trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends FreeSeqFactory[CC] { import SeqFactory.UnapplySeqWrapper final def unapplySeq[A](x: CC[A] @uncheckedVariance): UnapplySeqWrapper[A] = new UnapplySeqWrapper(x) // TODO is uncheckedVariance sound here? } @@ -303,7 +314,7 @@ object SeqFactory { class Delegate[CC[A] <: SeqOps[A, Seq, Seq[A]]](delegate: SeqFactory[CC]) extends SeqFactory[CC] { override def apply[A](elems: A*): CC[A] = delegate.apply(elems: _*) def empty[A]: CC[A] = delegate.empty - def from[E](it: IterableOnce[E]): CC[E] = delegate.from(it) + def from[E](it: IterableOnce[E]^): CC[E] = delegate.from(it) def newBuilder[A]: Builder[A, CC[A]] = delegate.newBuilder[A] } @@ -366,6 +377,8 @@ trait StrictOptimizedSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends SeqFac * @define Coll `Iterable` */ trait SpecificIterableFactory[-A, +C] extends Factory[A, C] { + this: SpecificIterableFactory[A, C] => + def empty: C def apply(xs: A*): C = fromSpecific(xs) def fill(n: Int)(elem: => A): C = fromSpecific(new View.Fill(n)(elem)) @@ -381,7 +394,7 @@ trait SpecificIterableFactory[-A, +C] extends Factory[A, C] { * @define coll collection * @define Coll `Iterable` */ -trait MapFactory[+CC[_, _]] extends Serializable { +trait MapFactory[+CC[_, _]] extends Serializable, Pure { /** * An empty Map @@ -391,7 +404,7 @@ trait MapFactory[+CC[_, _]] extends Serializable { /** * A collection of type Map generated from given iterable object. */ - def from[K, V](it: IterableOnce[(K, V)]): CC[K, V] + def from[K, V](it: IterableOnce[(K, V)]^): CC[K, V] /** * A collection of type Map that contains given key/value bindings. @@ -424,20 +437,20 @@ object MapFactory { @SerialVersionUID(3L) private[this] class ToFactory[K, V, CC[_, _]](factory: MapFactory[CC]) extends Factory[(K, V), CC[K, V]] with Serializable { - def fromSpecific(it: IterableOnce[(K, V)]): CC[K, V] = factory.from[K, V](it) + def fromSpecific(it: IterableOnce[(K, V)]^): CC[K, V] = factory.from[K, V](it) def newBuilder: Builder[(K, V), CC[K, V]] = factory.newBuilder[K, V] } implicit def toBuildFrom[K, V, CC[_, _]](factory: MapFactory[CC]): BuildFrom[Any, (K, V), CC[K, V]] = new BuildFrom[Any, (K, V), CC[K, V]] { - def fromSpecific(from: Any)(it: IterableOnce[(K, V)]) = factory.from(it) + def fromSpecific(from: Any)(it: IterableOnce[(K, V)]^) = factory.from(it) def newBuilder(from: Any) = factory.newBuilder[K, V] } @SerialVersionUID(3L) class Delegate[C[_, _]](delegate: MapFactory[C]) extends MapFactory[C] { override def apply[K, V](elems: (K, V)*): C[K, V] = delegate.apply(elems: _*) - def from[K, V](it: IterableOnce[(K, V)]): C[K, V] = delegate.from(it) + def from[K, V](it: IterableOnce[(K, V)]^): C[K, V] = delegate.from(it) def empty[K, V]: C[K, V] = delegate.empty def newBuilder[K, V]: Builder[(K, V), C[K, V]] = delegate.newBuilder } @@ -454,9 +467,9 @@ object MapFactory { * @define coll collection * @define Coll `Iterable` */ -trait EvidenceIterableFactory[+CC[_], Ev[_]] extends Serializable { +trait EvidenceIterableFactory[+CC[_], Ev[_]] extends Serializable, Pure { - def from[E : Ev](it: IterableOnce[E]): CC[E] + def from[E : Ev](it: IterableOnce[E]^): CC[E] def empty[A : Ev]: CC[A] @@ -517,13 +530,13 @@ object EvidenceIterableFactory { @SerialVersionUID(3L) private[this] class ToFactory[Ev[_], A: Ev, CC[_]](factory: EvidenceIterableFactory[CC, Ev]) extends Factory[A, CC[A]] with Serializable { - def fromSpecific(it: IterableOnce[A]): CC[A] = factory.from[A](it) + def fromSpecific(it: IterableOnce[A]^): CC[A] = factory.from[A](it) def newBuilder: Builder[A, CC[A]] = factory.newBuilder[A] } implicit def toBuildFrom[Ev[_], A: Ev, CC[_]](factory: EvidenceIterableFactory[CC, Ev]): BuildFrom[Any, A, CC[A]] = new EvidenceIterableFactoryToBuildFrom(factory) private class EvidenceIterableFactoryToBuildFrom[Ev[_], A: Ev, CC[_]](factory: EvidenceIterableFactory[CC, Ev]) extends BuildFrom[Any, A, CC[A]] { - def fromSpecific(from: Any)(it: IterableOnce[A]): CC[A] = factory.from[A](it) + def fromSpecific(from: Any)(it: IterableOnce[A]^): CC[A] = factory.from[A](it) def newBuilder(from: Any): Builder[A, CC[A]] = factory.newBuilder[A] } @@ -531,7 +544,7 @@ object EvidenceIterableFactory { class Delegate[CC[_], Ev[_]](delegate: EvidenceIterableFactory[CC, Ev]) extends EvidenceIterableFactory[CC, Ev] { override def apply[A: Ev](xs: A*): CC[A] = delegate.apply(xs: _*) def empty[A : Ev]: CC[A] = delegate.empty - def from[E : Ev](it: IterableOnce[E]): CC[E] = delegate.from(it) + def from[E : Ev](it: IterableOnce[E]^): CC[E] = delegate.from(it) def newBuilder[A : Ev]: Builder[A, CC[A]] = delegate.newBuilder[A] } } @@ -668,7 +681,7 @@ object ClassTagIterableFactory { @SerialVersionUID(3L) class AnyIterableDelegate[CC[_]](delegate: ClassTagIterableFactory[CC]) extends IterableFactory[CC] { def empty[A]: CC[A] = delegate.empty(ClassTag.Any).asInstanceOf[CC[A]] - def from[A](it: IterableOnce[A]): CC[A] = delegate.from[Any](it)(ClassTag.Any).asInstanceOf[CC[A]] + def from[A](it: IterableOnce[A]^): CC[A] = delegate.from[Any](it)(ClassTag.Any).asInstanceOf[CC[A]] def newBuilder[A]: Builder[A, CC[A]] = delegate.newBuilder(ClassTag.Any).asInstanceOf[Builder[A, CC[A]]] override def apply[A](elems: A*): CC[A] = delegate.apply[Any](elems: _*)(ClassTag.Any).asInstanceOf[CC[A]] override def iterate[A](start: A, len: Int)(f: A => A): CC[A] = delegate.iterate[A](start, len)(f)(ClassTag.Any.asInstanceOf[ClassTag[A]]) @@ -734,10 +747,11 @@ trait StrictOptimizedClassTagSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extend * @define Coll `Iterable` */ trait SortedMapFactory[+CC[_, _]] extends Serializable { + this: SortedMapFactory[CC] => def empty[K : Ordering, V]: CC[K, V] - def from[K : Ordering, V](it: IterableOnce[(K, V)]): CC[K, V] + def from[K : Ordering, V](it: IterableOnce[(K, V)]^): CC[K, V] def apply[K : Ordering, V](elems: (K, V)*): CC[K, V] = from(elems) @@ -764,20 +778,20 @@ object SortedMapFactory { @SerialVersionUID(3L) private[this] class ToFactory[K : Ordering, V, CC[_, _]](factory: SortedMapFactory[CC]) extends Factory[(K, V), CC[K, V]] with Serializable { - def fromSpecific(it: IterableOnce[(K, V)]): CC[K, V] = factory.from[K, V](it) + def fromSpecific(it: IterableOnce[(K, V)]^): CC[K, V] = factory.from[K, V](it) def newBuilder: Builder[(K, V), CC[K, V]] = factory.newBuilder[K, V] } implicit def toBuildFrom[K : Ordering, V, CC[_, _]](factory: SortedMapFactory[CC]): BuildFrom[Any, (K, V), CC[K, V]] = new SortedMapFactoryToBuildFrom(factory) private class SortedMapFactoryToBuildFrom[K : Ordering, V, CC[_, _]](factory: SortedMapFactory[CC]) extends BuildFrom[Any, (K, V), CC[K, V]] { - def fromSpecific(from: Any)(it: IterableOnce[(K, V)]) = factory.from(it) + def fromSpecific(from: Any)(it: IterableOnce[(K, V)]^) = factory.from(it) def newBuilder(from: Any) = factory.newBuilder[K, V] } @SerialVersionUID(3L) class Delegate[CC[_, _]](delegate: SortedMapFactory[CC]) extends SortedMapFactory[CC] { override def apply[K: Ordering, V](elems: (K, V)*): CC[K, V] = delegate.apply(elems: _*) - def from[K : Ordering, V](it: IterableOnce[(K, V)]): CC[K, V] = delegate.from(it) + def from[K : Ordering, V](it: IterableOnce[(K, V)]^): CC[K, V] = delegate.from(it) def empty[K : Ordering, V]: CC[K, V] = delegate.empty def newBuilder[K : Ordering, V]: Builder[(K, V), CC[K, V]] = delegate.newBuilder } diff --git a/scala2-library-cc/src/scala/collection/Hashing.scala b/scala2-library-cc/src/scala/collection/Hashing.scala index 4e1fd872b8b5..772dcf5c65da 100644 --- a/scala2-library-cc/src/scala/collection/Hashing.scala +++ b/scala2-library-cc/src/scala/collection/Hashing.scala @@ -12,6 +12,7 @@ package scala package collection +import language.experimental.captureChecking protected[collection] object Hashing { diff --git a/scala2-library-cc/src/scala/collection/IndexedSeq.scala b/scala2-library-cc/src/scala/collection/IndexedSeq.scala index c26e771004d8..998d1a5a635f 100644 --- a/scala2-library-cc/src/scala/collection/IndexedSeq.scala +++ b/scala2-library-cc/src/scala/collection/IndexedSeq.scala @@ -17,6 +17,9 @@ import scala.annotation.{nowarn, tailrec} import scala.collection.Searching.{Found, InsertionPoint, SearchResult} import scala.collection.Stepper.EfficientSplit import scala.math.Ordering +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure + /** Base trait for indexed sequences that have efficient `apply` and `length` */ trait IndexedSeq[+A] extends Seq[A] @@ -32,7 +35,7 @@ trait IndexedSeq[+A] extends Seq[A] object IndexedSeq extends SeqFactory.Delegate[IndexedSeq](immutable.IndexedSeq) /** Base trait for indexed Seq operations */ -trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self => +trait IndexedSeqOps[+A, +CC[_], +C] extends Any with IndexedSeqViewOps[A, CC, C] with SeqOps[A, CC, C] { self => def iterator: Iterator[A] = view.iterator @@ -85,7 +88,7 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self => override def dropRight(n: Int): C = fromSpecific(new IndexedSeqView.DropRight(this, n)) - override def map[B](f: A => B): CC[B] = iterableFactory.from(new IndexedSeqView.Map(this, f)) + override def map[B](f: A => B): CC[B] = iterableFactory.from(new IndexedSeqView.Map(this, f)).unsafeAssumePure override def reverse: C = fromSpecific(new IndexedSeqView.Reverse(this)) @@ -117,7 +120,7 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self => override def knownSize: Int = length - override final def lengthCompare(that: Iterable[_]): Int = { + override final def lengthCompare(that: Iterable[_]^): Int = { val res = that.sizeCompare(length) // can't just invert the result, because `-Int.MinValue == Int.MinValue` if (res == Int.MinValue) 1 else -res diff --git a/scala2-library-cc/src/scala/collection/IndexedSeqView.scala b/scala2-library-cc/src/scala/collection/IndexedSeqView.scala index 737f032d2060..a16e06fa707d 100644 --- a/scala2-library-cc/src/scala/collection/IndexedSeqView.scala +++ b/scala2-library-cc/src/scala/collection/IndexedSeqView.scala @@ -14,33 +14,38 @@ package scala package collection import scala.annotation.nowarn +import language.experimental.captureChecking +trait IndexedSeqViewOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { + self: IndexedSeqViewOps[A, CC, C]^ => +} /** View defined in terms of indexing a range */ -trait IndexedSeqView[+A] extends IndexedSeqOps[A, View, View[A]] with SeqView[A] { self => +trait IndexedSeqView[+A] extends IndexedSeqViewOps[A, View, View[A]] with SeqView[A] { + self: IndexedSeqView[A]^ => - override def view: IndexedSeqView[A] = this + override def view: IndexedSeqView[A]^{this} = this @deprecated("Use .view.slice(from, until) instead of .view(from, until)", "2.13.0") - override def view(from: Int, until: Int): IndexedSeqView[A] = view.slice(from, until) - - override def iterator: Iterator[A] = new IndexedSeqView.IndexedSeqViewIterator(this) - override def reverseIterator: Iterator[A] = new IndexedSeqView.IndexedSeqViewReverseIterator(this) - - override def appended[B >: A](elem: B): IndexedSeqView[B] = new IndexedSeqView.Appended(this, elem) - override def prepended[B >: A](elem: B): IndexedSeqView[B] = new IndexedSeqView.Prepended(elem, this) - override def take(n: Int): IndexedSeqView[A] = new IndexedSeqView.Take(this, n) - override def takeRight(n: Int): IndexedSeqView[A] = new IndexedSeqView.TakeRight(this, n) - override def drop(n: Int): IndexedSeqView[A] = new IndexedSeqView.Drop(this, n) - override def dropRight(n: Int): IndexedSeqView[A] = new IndexedSeqView.DropRight(this, n) - override def map[B](f: A => B): IndexedSeqView[B] = new IndexedSeqView.Map(this, f) - override def reverse: IndexedSeqView[A] = new IndexedSeqView.Reverse(this) - override def slice(from: Int, until: Int): IndexedSeqView[A] = new IndexedSeqView.Slice(this, from, until) - override def tapEach[U](f: A => U): IndexedSeqView[A] = new IndexedSeqView.Map(this, { (a: A) => f(a); a}) - - def concat[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new IndexedSeqView.Concat(this, suffix) - def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new IndexedSeqView.Concat(this, suffix) - def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new IndexedSeqView.Concat(prefix, this) + override def view(from: Int, until: Int): IndexedSeqView[A]^{this} = view.slice(from, until) + + override def iterator: Iterator[A]^{this} = new IndexedSeqView.IndexedSeqViewIterator(this) + override def reverseIterator: Iterator[A]^{this} = new IndexedSeqView.IndexedSeqViewReverseIterator(this) + + override def appended[B >: A](elem: B): IndexedSeqView[B]^{this} = new IndexedSeqView.Appended(this, elem) + override def prepended[B >: A](elem: B): IndexedSeqView[B]^{this} = new IndexedSeqView.Prepended(elem, this) + override def take(n: Int): IndexedSeqView[A]^{this} = new IndexedSeqView.Take(this, n) + override def takeRight(n: Int): IndexedSeqView[A]^{this} = new IndexedSeqView.TakeRight(this, n) + override def drop(n: Int): IndexedSeqView[A]^{this} = new IndexedSeqView.Drop(this, n) + override def dropRight(n: Int): IndexedSeqView[A]^{this} = new IndexedSeqView.DropRight(this, n) + override def map[B](f: A => B): IndexedSeqView[B]^{this, f} = new IndexedSeqView.Map(this, f) + override def reverse: IndexedSeqView[A]^{this} = new IndexedSeqView.Reverse(this) + override def slice(from: Int, until: Int): IndexedSeqView[A]^{this} = new IndexedSeqView.Slice(this, from, until) + override def tapEach[U](f: A => U): IndexedSeqView[A]^{this, f} = new IndexedSeqView.Map(this, { (a: A) => f(a); a}) + + def concat[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B]^{this} = new IndexedSeqView.Concat(this, suffix) + def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B]^{this} = new IndexedSeqView.Concat(this, suffix) + def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B]^{this} = new IndexedSeqView.Concat(prefix, this) @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix: String = "IndexedSeqView" @@ -49,7 +54,8 @@ trait IndexedSeqView[+A] extends IndexedSeqOps[A, View, View[A]] with SeqView[A] object IndexedSeqView { @SerialVersionUID(3L) - private[collection] class IndexedSeqViewIterator[A](self: IndexedSeqView[A]) extends AbstractIterator[A] with Serializable { + private[collection] class IndexedSeqViewIterator[A](self: IndexedSeqView[A]^) extends AbstractIterator[A] with Serializable { + this: IndexedSeqViewIterator[A]^ => private[this] var current = 0 private[this] var remainder = self.length override def knownSize: Int = remainder @@ -63,7 +69,7 @@ object IndexedSeqView { r } else Iterator.empty.next() - override def drop(n: Int): Iterator[A] = { + override def drop(n: Int): Iterator[A]^{this} = { if (n > 0) { current += n remainder = Math.max(0, remainder - n) @@ -71,7 +77,7 @@ object IndexedSeqView { this } - override protected def sliceIterator(from: Int, until: Int): Iterator[A] = { + override protected def sliceIterator(from: Int, until: Int): Iterator[A]^{this} = { def formatRange(value : Int) : Int = if (value < 0) 0 else if (value > remainder) remainder else value @@ -83,7 +89,8 @@ object IndexedSeqView { } } @SerialVersionUID(3L) - private[collection] class IndexedSeqViewReverseIterator[A](self: IndexedSeqView[A]) extends AbstractIterator[A] with Serializable { + private[collection] class IndexedSeqViewReverseIterator[A](self: IndexedSeqView[A]^) extends AbstractIterator[A] with Serializable { + this: IndexedSeqViewReverseIterator[A]^ => private[this] var remainder = self.length private[this] var pos = remainder - 1 @inline private[this] def _hasNext: Boolean = remainder > 0 @@ -98,7 +105,7 @@ object IndexedSeqView { // from < 0 means don't move pos, until < 0 means don't limit remainder // - override protected def sliceIterator(from: Int, until: Int): Iterator[A] = { + override protected def sliceIterator(from: Int, until: Int): Iterator[A]^{this} = { if (_hasNext) { if (remainder <= from) remainder = 0 // exhausted by big skip else if (from <= 0) { // no skip, pos is same @@ -117,47 +124,47 @@ object IndexedSeqView { } } - /** An `IndexedSeqOps` whose collection type and collection type constructor are unknown */ - type SomeIndexedSeqOps[A] = IndexedSeqOps[A, AnyConstr, _] + /** An `IndexedSeqViewOps` whose collection type and collection type constructor are unknown */ + type SomeIndexedSeqOps[A] = IndexedSeqViewOps[A, AnyConstr, _] @SerialVersionUID(3L) - class Id[+A](underlying: SomeIndexedSeqOps[A]) + class Id[+A](underlying: SomeIndexedSeqOps[A]^) extends SeqView.Id(underlying) with IndexedSeqView[A] @SerialVersionUID(3L) - class Appended[+A](underlying: SomeIndexedSeqOps[A], elem: A) + class Appended[+A](underlying: SomeIndexedSeqOps[A]^, elem: A) extends SeqView.Appended(underlying, elem) with IndexedSeqView[A] @SerialVersionUID(3L) - class Prepended[+A](elem: A, underlying: SomeIndexedSeqOps[A]) + class Prepended[+A](elem: A, underlying: SomeIndexedSeqOps[A]^) extends SeqView.Prepended(elem, underlying) with IndexedSeqView[A] @SerialVersionUID(3L) - class Concat[A](prefix: SomeIndexedSeqOps[A], suffix: SomeIndexedSeqOps[A]) + class Concat[A](prefix: SomeIndexedSeqOps[A]^, suffix: SomeIndexedSeqOps[A]^) extends SeqView.Concat[A](prefix, suffix) with IndexedSeqView[A] @SerialVersionUID(3L) - class Take[A](underlying: SomeIndexedSeqOps[A], n: Int) + class Take[A](underlying: SomeIndexedSeqOps[A]^, n: Int) extends SeqView.Take(underlying, n) with IndexedSeqView[A] @SerialVersionUID(3L) - class TakeRight[A](underlying: SomeIndexedSeqOps[A], n: Int) + class TakeRight[A](underlying: SomeIndexedSeqOps[A]^, n: Int) extends SeqView.TakeRight(underlying, n) with IndexedSeqView[A] @SerialVersionUID(3L) - class Drop[A](underlying: SomeIndexedSeqOps[A], n: Int) + class Drop[A](underlying: SomeIndexedSeqOps[A]^, n: Int) extends SeqView.Drop[A](underlying, n) with IndexedSeqView[A] @SerialVersionUID(3L) - class DropRight[A](underlying: SomeIndexedSeqOps[A], n: Int) + class DropRight[A](underlying: SomeIndexedSeqOps[A]^, n: Int) extends SeqView.DropRight[A](underlying, n) with IndexedSeqView[A] @SerialVersionUID(3L) - class Map[A, B](underlying: SomeIndexedSeqOps[A], f: A => B) + class Map[A, B](underlying: SomeIndexedSeqOps[A]^, f: A => B) extends SeqView.Map(underlying, f) with IndexedSeqView[B] @SerialVersionUID(3L) - class Reverse[A](underlying: SomeIndexedSeqOps[A]) extends SeqView.Reverse[A](underlying) with IndexedSeqView[A] { + class Reverse[A](underlying: SomeIndexedSeqOps[A]^) extends SeqView.Reverse[A](underlying) with IndexedSeqView[A] { override def reverse: IndexedSeqView[A] = underlying match { case x: IndexedSeqView[A] => x case _ => super.reverse @@ -165,7 +172,7 @@ object IndexedSeqView { } @SerialVersionUID(3L) - class Slice[A](underlying: SomeIndexedSeqOps[A], from: Int, until: Int) extends AbstractIndexedSeqView[A] { + class Slice[A](underlying: SomeIndexedSeqOps[A]^, from: Int, until: Int) extends AbstractIndexedSeqView[A] { protected val lo = from max 0 protected val hi = (until max 0) min underlying.length protected val len = (hi - lo) max 0 diff --git a/scala2-library-cc/src/scala/collection/Iterable.scala b/scala2-library-cc/src/scala/collection/Iterable.scala index 9ee4e5083d47..bca80d7be108 100644 --- a/scala2-library-cc/src/scala/collection/Iterable.scala +++ b/scala2-library-cc/src/scala/collection/Iterable.scala @@ -17,6 +17,7 @@ import scala.annotation.nowarn import scala.annotation.unchecked.uncheckedVariance import scala.collection.mutable.Builder import scala.collection.View.{LeftPartitionMapped, RightPartitionMapped} +import language.experimental.captureChecking /** Base trait for generic collections. * @@ -28,6 +29,7 @@ import scala.collection.View.{LeftPartitionMapped, RightPartitionMapped} trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterable[A]] with IterableFactoryDefaults[A, Iterable] { + this: Iterable[A]^ => // The collection itself @deprecated("toIterable is internal and will be made protected; its name is similar to `toList` or `toSeq`, but it doesn't copy non-immutable collections", "2.13.7") @@ -94,7 +96,7 @@ trait Iterable[+A] extends IterableOnce[A] * @return a decorator `LazyZip2` that allows strict operations to be performed on the lazily evaluated pairs * or chained calls to `lazyZip`. Implicit conversion to `Iterable[(A, B)]` is also supported. */ - def lazyZip[B](that: Iterable[B]): LazyZip2[A, B, this.type] = new LazyZip2(this, this, that) + def lazyZip[B](that: Iterable[B]^): LazyZip2[A, B, this.type]^{this, that} = new LazyZip2(this, this, that) } /** Base trait for Iterable operations @@ -132,29 +134,31 @@ trait Iterable[+A] extends IterableOnce[A] * and may be nondeterministic. */ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with IterableOnceOps[A, CC, C] { + this: IterableOps[A, CC, C]^ => + /** * @return This collection as an `Iterable[A]`. No new collection will be built if `this` is already an `Iterable[A]`. */ // Should be `protected def asIterable`, or maybe removed altogether if it's not needed @deprecated("toIterable is internal and will be made protected; its name is similar to `toList` or `toSeq`, but it doesn't copy non-immutable collections", "2.13.7") - def toIterable: Iterable[A] + def toIterable: Iterable[A]^{this} /** Converts this $coll to an unspecified Iterable. Will return * the same collection if this instance is already Iterable. * @return An Iterable containing all elements of this $coll. */ @deprecated("toTraversable is internal and will be made protected; its name is similar to `toList` or `toSeq`, but it doesn't copy non-immutable collections", "2.13.0") - final def toTraversable: Traversable[A] = toIterable + final def toTraversable: Traversable[A]^{this} = toIterable override def isTraversableAgain: Boolean = true /** * @return This collection as a `C`. */ - protected def coll: C + protected def coll: C^{this} @deprecated("Use coll instead of repr in a collection implementation, use the collection value itself from the outside", "2.13.0") - final def repr: C = coll + final def repr: C^{this} = coll /** * Defines how to turn a given `Iterable[A]` into a collection of type `C`. @@ -174,7 +178,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * `Iterable[A]` obtained from `this` collection (as it is the case in the * implementations of operations where we use a `View[A]`), it is safe. */ - protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]): C + protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]^): C^{coll} /** The companion object of this ${coll}, providing various factory methods. * @@ -251,7 +255,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable def lastOption: Option[A] = if (isEmpty) None else Some(last) /** A view over the elements of this collection. */ - def view: View[A] = View.fromIteratorProvider(() => iterator) + def view: View[A]^{this} = View.fromIteratorProvider(() => iterator) /** Compares the size of this $coll to a test value. * @@ -301,7 +305,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * this.sizeIs > size // this.sizeCompare(size) > 0 * }}} */ - @inline final def sizeIs: IterableOps.SizeCompareOps = new IterableOps.SizeCompareOps(this) + @inline final def sizeIs: IterableOps.SizeCompareOps^{this} = new IterableOps.SizeCompareOps(this) /** Compares the size of this $coll to the size of another `Iterable`. * @@ -317,7 +321,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * is `O(this.size min that.size)` instead of `O(this.size + that.size)`. * The method should be overridden if computing `size` is cheap and `knownSize` returns `-1`. */ - def sizeCompare(that: Iterable[_]): Int = { + def sizeCompare(that: Iterable[_]^): Int = { val thatKnownSize = that.knownSize if (thatKnownSize >= 0) this sizeCompare thatKnownSize @@ -342,7 +346,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable /** A view over a slice of the elements of this collection. */ @deprecated("Use .view.slice(from, until) instead of .view(from, until)", "2.13.0") - def view(from: Int, until: Int): View[A] = view.slice(from, until) + def view(from: Int, until: Int): View[A]^{this} = view.slice(from, until) /** Transposes this $coll of iterable collections into * a $coll of ${coll}s. @@ -378,7 +382,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @throws IllegalArgumentException if all collections in this $coll * are not of the same size. */ - def transpose[B](implicit asIterable: A => /*<: /*<: Boolean): C = fromSpecific(new View.Filter(this, pred, isFlipped = false)) + def filter(pred: A => Boolean): C^{this, pred} = fromSpecific(new View.Filter(this, pred, isFlipped = false)) - def filterNot(pred: A => Boolean): C = fromSpecific(new View.Filter(this, pred, isFlipped = true)) + def filterNot(pred: A => Boolean): C^{this, pred} = fromSpecific(new View.Filter(this, pred, isFlipped = true)) /** Creates a non-strict filter of this $coll. * @@ -417,7 +421,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * All these operations apply to those elements of this $coll * which satisfy the predicate `p`. */ - def withFilter(p: A => Boolean): collection.WithFilter[A, CC] = new IterableOps.WithFilter(this, p) + def withFilter(p: A => Boolean): collection.WithFilter[A, CC]^{this, p} = new IterableOps.WithFilter(this, p) /** A pair of, first, all elements that satisfy predicate `p` and, second, * all elements that do not. Interesting because it splits a collection in two. @@ -426,15 +430,15 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * Strict collections have an overridden version of `partition` in `StrictOptimizedIterableOps`, * which requires only a single traversal. */ - def partition(p: A => Boolean): (C, C) = { + def partition(p: A => Boolean): (C^{this, p}, C^{this, p}) = { val first = new View.Filter(this, p, false) val second = new View.Filter(this, p, true) (fromSpecific(first), fromSpecific(second)) } - override def splitAt(n: Int): (C, C) = (take(n), drop(n)) + override def splitAt(n: Int): (C^{this}, C^{this}) = (take(n), drop(n)) - def take(n: Int): C = fromSpecific(new View.Take(this, n)) + def take(n: Int): C^{this} = fromSpecific(new View.Take(this, n)) /** Selects the last ''n'' elements. * $orderDependent @@ -443,7 +447,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * or else the whole $coll, if it has less than `n` elements. * If `n` is negative, returns an empty $coll. */ - def takeRight(n: Int): C = fromSpecific(new View.TakeRight(this, n)) + def takeRight(n: Int): C^{this} = fromSpecific(new View.TakeRight(this, n)) /** Takes longest prefix of elements that satisfy a predicate. * $orderDependent @@ -451,11 +455,11 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return the longest prefix of this $coll whose elements all satisfy * the predicate `p`. */ - def takeWhile(p: A => Boolean): C = fromSpecific(new View.TakeWhile(this, p)) + def takeWhile(p: A => Boolean): C^{this, p} = fromSpecific(new View.TakeWhile(this, p)) - def span(p: A => Boolean): (C, C) = (takeWhile(p), dropWhile(p)) + def span(p: A => Boolean): (C^{this, p}, C^{this, p}) = (takeWhile(p), dropWhile(p)) - def drop(n: Int): C = fromSpecific(new View.Drop(this, n)) + def drop(n: Int): C^{this} = fromSpecific(new View.Drop(this, n)) /** Selects all elements except last ''n'' ones. * $orderDependent @@ -464,9 +468,9 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * empty $coll, if this $coll has less than `n` elements. * If `n` is negative, don't drop any elements. */ - def dropRight(n: Int): C = fromSpecific(new View.DropRight(this, n)) + def dropRight(n: Int): C^{this} = fromSpecific(new View.DropRight(this, n)) - def dropWhile(p: A => Boolean): C = fromSpecific(new View.DropWhile(this, p)) + def dropWhile(p: A => Boolean): C^{this, p} = fromSpecific(new View.DropWhile(this, p)) /** Partitions elements in fixed size ${coll}s. * @see [[scala.collection.Iterator]], method `grouped` @@ -475,7 +479,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return An iterator producing ${coll}s of size `size`, except the * last will be less than size `size` if the elements don't divide evenly. */ - def grouped(size: Int): Iterator[C] = + def grouped(size: Int): Iterator[C^{this}]^{this} = iterator.grouped(size).map(fromSpecific) /** Groups elements in fixed size blocks by passing a "sliding window" @@ -497,7 +501,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @example `List(1, 2).sliding(2) = Iterator(List(1, 2))` * @example `List(1, 2, 3).sliding(2) = Iterator(List(1, 2), List(2, 3))` */ - def sliding(size: Int): Iterator[C] = sliding(size, 1) + def sliding(size: Int): Iterator[C^{this}]^{this} = sliding(size, 1) /** Groups elements in fixed size blocks by passing a "sliding window" * over them (as opposed to partitioning them, as is done in grouped.) @@ -516,13 +520,13 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * element (which may be the only element) will be smaller * if there are fewer than `size` elements remaining to be grouped. * @example `List(1, 2, 3, 4, 5).sliding(2, 2) = Iterator(List(1, 2), List(3, 4), List(5))` - * @example `List(1, 2, 3, 4, 5, 6).sliding(2, 3) = Iterator(List(1, 2), List(4, 5))` + * @example `List(1, 2, 3, 4, 5, 6).sliding(2, 3) = Iterator(List(1, 2), List(4, 5))` */ - def sliding(size: Int, step: Int): Iterator[C] = + def sliding(size: Int, step: Int): Iterator[C^{this}]^{this} = iterator.sliding(size, step).map(fromSpecific) /** The rest of the collection without its first element. */ - def tail: C = { + def tail: C^{this} = { if (isEmpty) throw new UnsupportedOperationException drop(1) } @@ -530,12 +534,12 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable /** The initial part of the collection without its last element. * $willForceEvaluation */ - def init: C = { + def init: C^{this} = { if (isEmpty) throw new UnsupportedOperationException dropRight(1) } - def slice(from: Int, until: Int): C = + def slice(from: Int, until: Int): C^{this} = fromSpecific(new View.Drop(new View.Take(this, until), from)) /** Partitions this $coll into a map of ${coll}s according to some discriminator function. @@ -645,9 +649,9 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * * @return a new $coll containing the prefix scan of the elements in this $coll */ - def scan[B >: A](z: B)(op: (B, B) => B): CC[B] = scanLeft(z)(op) + def scan[B >: A](z: B)(op: (B, B) => B): CC[B]^{this, op} = scanLeft(z)(op) - def scanLeft[B](z: B)(op: (B, A) => B): CC[B] = iterableFactory.from(new View.ScanLeft(this, z, op)) + def scanLeft[B](z: B)(op: (B, A) => B): CC[B]^{this, op} = iterableFactory.from(new View.ScanLeft(this, z, op)) /** Produces a collection containing cumulative results of applying the operator going right to left. * The head of the collection is the last cumulative result. @@ -665,7 +669,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @param op the binary operator applied to the intermediate result and the element * @return collection with intermediate results */ - def scanRight[B](z: B)(op: (A, B) => B): CC[B] = { + def scanRight[B](z: B)(op: (A, B) => B): CC[B]^{this, op} = { class Scanner extends runtime.AbstractFunction1[A, Unit] { var acc = z var scanned = acc :: immutable.Nil @@ -679,13 +683,13 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable iterableFactory.from(scanner.scanned) } - def map[B](f: A => B): CC[B] = iterableFactory.from(new View.Map(this, f)) + def map[B](f: A => B): CC[B]^{this, f} = iterableFactory.from(new View.Map(this, f)) - def flatMap[B](f: A => IterableOnce[B]): CC[B] = iterableFactory.from(new View.FlatMap(this, f)) + def flatMap[B](f: A => IterableOnce[B]^): CC[B]^{this, f} = iterableFactory.from(new View.FlatMap(this, f)) - def flatten[B](implicit asIterable: A => IterableOnce[B]): CC[B] = flatMap(asIterable) + def flatten[B](implicit asIterable: A -> IterableOnce[B]): CC[B]^{this} = flatMap(asIterable) - def collect[B](pf: PartialFunction[A, B]): CC[B] = + def collect[B](pf: PartialFunction[A, B]^): CC[B]^{this, pf} = iterableFactory.from(new View.Collect(this, pf)) /** Applies a function `f` to each element of the $coll and returns a pair of ${coll}s: the first one @@ -706,12 +710,12 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @tparam A2 the element type of the second resulting collection * @param f the 'split function' mapping the elements of this $coll to an [[scala.util.Either]] * - * @return a pair of ${coll}s: the first one made of those values returned by `f` that were wrapped in [[scala.util.Left]], + * @return a pair of ${coll}s: the first one made of those values returned by `f` that were wrapped in [[scala.util.Left]], * and the second one made of those wrapped in [[scala.util.Right]]. */ - def partitionMap[A1, A2](f: A => Either[A1, A2]): (CC[A1], CC[A2]) = { - val left: View[A1] = new LeftPartitionMapped(this, f) - val right: View[A2] = new RightPartitionMapped(this, f) + def partitionMap[A1, A2](f: A => Either[A1, A2]): (CC[A1]^{this, f}, CC[A2]^{this, f}) = { + val left: View[A1]^{f, this} = new LeftPartitionMapped(this, f) + val right: View[A2]^{f, this} = new RightPartitionMapped(this, f) (iterableFactory.from(left), iterableFactory.from(right)) } @@ -724,13 +728,13 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return a new $coll which contains all elements * of this $coll followed by all elements of `suffix`. */ - def concat[B >: A](suffix: IterableOnce[B]): CC[B] = iterableFactory.from(suffix match { + def concat[B >: A](suffix: IterableOnce[B]^): CC[B]^{this, suffix} = iterableFactory.from(suffix match { case xs: Iterable[B] => new View.Concat(this, xs) case xs => iterator ++ suffix.iterator }) /** Alias for `concat` */ - @`inline` final def ++ [B >: A](suffix: IterableOnce[B]): CC[B] = concat(suffix) + @`inline` final def ++ [B >: A](suffix: IterableOnce[B]^): CC[B]^{this, suffix} = concat(suffix) /** Returns a $coll formed from this $coll and another iterable collection * by combining corresponding elements in pairs. @@ -741,12 +745,12 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return a new $coll containing pairs consisting of corresponding elements of this $coll and `that`. * The length of the returned collection is the minimum of the lengths of this $coll and `that`. */ - def zip[B](that: IterableOnce[B]): CC[(A @uncheckedVariance, B)] = iterableFactory.from(that match { // sound bcs of VarianceNote + def zip[B](that: IterableOnce[B]^): CC[(A @uncheckedVariance, B)]^{this, that} = iterableFactory.from(that match { // sound bcs of VarianceNote case that: Iterable[B] => new View.Zip(this, that) case _ => iterator.zip(that) }) - def zipWithIndex: CC[(A @uncheckedVariance, Int)] = iterableFactory.from(new View.ZipWithIndex(this)) + def zipWithIndex: CC[(A @uncheckedVariance, Int)]^{this} = iterableFactory.from(new View.ZipWithIndex(this)) /** Returns a $coll formed from this $coll and another iterable collection * by combining corresponding elements in pairs. @@ -762,7 +766,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * If this $coll is shorter than `that`, `thisElem` values are used to pad the result. * If `that` is shorter than this $coll, `thatElem` values are used to pad the result. */ - def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): CC[(A1, B)] = iterableFactory.from(new View.ZipAll(this, that, thisElem, thatElem)) + def zipAll[A1 >: A, B](that: Iterable[B]^, thisElem: A1, thatElem: B): CC[(A1, B)]^{this, that} = iterableFactory.from(new View.ZipAll(this, that, thisElem, thatElem)) /** Converts this $coll of pairs into two collections of the first and second * half of each pair. @@ -783,9 +787,9 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return a pair of ${coll}s, containing the first, respectively second * half of each element pair of this $coll. */ - def unzip[A1, A2](implicit asPair: A => (A1, A2)): (CC[A1], CC[A2]) = { - val first: View[A1] = new View.Map[A, A1](this, asPair(_)._1) - val second: View[A2] = new View.Map[A, A2](this, asPair(_)._2) + def unzip[A1, A2](implicit asPair: A -> (A1, A2)): (CC[A1]^{this}, CC[A2]^{this}) = { + val first: View[A1]^{this} = new View.Map[A, A1](this, asPair(_)._1) + val second: View[A2]^{this} = new View.Map[A, A2](this, asPair(_)._2) (iterableFactory.from(first), iterableFactory.from(second)) } @@ -810,10 +814,10 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return a triple of ${coll}s, containing the first, second, respectively * third member of each element triple of this $coll. */ - def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)): (CC[A1], CC[A2], CC[A3]) = { - val first: View[A1] = new View.Map[A, A1](this, asTriple(_)._1) - val second: View[A2] = new View.Map[A, A2](this, asTriple(_)._2) - val third: View[A3] = new View.Map[A, A3](this, asTriple(_)._3) + def unzip3[A1, A2, A3](implicit asTriple: A -> (A1, A2, A3)): (CC[A1]^{this}, CC[A2]^{this}, CC[A3]^{this}) = { + val first: View[A1]^{this} = new View.Map[A, A1](this, asTriple(_)._1) + val second: View[A2]^{this} = new View.Map[A, A2](this, asTriple(_)._2) + val third: View[A3]^{this} = new View.Map[A, A3](this, asTriple(_)._3) (iterableFactory.from(first), iterableFactory.from(second), iterableFactory.from(third)) } @@ -824,7 +828,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return an iterator over all the tails of this $coll * @example `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)` */ - def tails: Iterator[C] = iterateUntilEmpty(_.tail) + def tails: Iterator[C^{this}]^{this} = iterateUntilEmpty(_.tail) /** Iterates over the inits of this $coll. The first value will be this * $coll and the final one will be an empty $coll, with the intervening @@ -835,21 +839,24 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * @return an iterator over all the inits of this $coll * @example `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)` */ - def inits: Iterator[C] = iterateUntilEmpty(_.init) + def inits: Iterator[C^{this}]^{this} = iterateUntilEmpty(_.init) - override def tapEach[U](f: A => U): C = fromSpecific(new View.Map(this, { (a: A) => f(a); a })) + override def tapEach[U](f: A => U): C^{this, f} = fromSpecific(new View.Map(this, { (a: A) => f(a); a })) // A helper for tails and inits. - private[this] def iterateUntilEmpty(f: Iterable[A] => Iterable[A]): Iterator[C] = { + private[this] def iterateUntilEmpty(f: Iterable[A]^{this} => Iterable[A]^{this}): Iterator[C^{this}]^{this, f} = { // toIterable ties the knot between `this: IterableOnceOps[A, CC, C]` and `this.tail: C` // `this.tail.tail` doesn't compile as `C` is unbounded // `Iterable.from(this)` would eagerly copy non-immutable collections - val it = Iterator.iterate(toIterable: @nowarn("cat=deprecation"))(f).takeWhile(_.nonEmpty) + val it = Iterator.iterate(toIterable: @nowarn("cat=deprecation"))(f) + .takeWhile((itble: Iterable[A]^) => itble.iterator.nonEmpty) + // CC TODO type annotation for itble needed. + // The previous code `.takeWhile(_.iterator.nonEmpty)` does not work. (it ++ Iterator.single(Iterable.empty)).map(fromSpecific) } @deprecated("Use ++ instead of ++: for collections of type Iterable", "2.13.0") - def ++:[B >: A](that: IterableOnce[B]): CC[B] = iterableFactory.from(that match { + def ++:[B >: A](that: IterableOnce[B]^): CC[B]^{this, that} = iterableFactory.from(that match { case xs: Iterable[B] => new View.Concat(xs, this) case _ => that.iterator ++ iterator }) @@ -862,7 +869,8 @@ object IterableOps { * These operations are implemented in terms of * [[scala.collection.IterableOps.sizeCompare(Int) `sizeCompare(Int)`]]. */ - final class SizeCompareOps private[collection](val it: IterableOps[_, AnyConstr, _]) extends AnyVal { + final class SizeCompareOps private[collection](val it: IterableOps[_, AnyConstr, _]^) extends AnyVal { + this: SizeCompareOps^{it} => /** Tests if the size of the collection is less than some value. */ @inline def <(size: Int): Boolean = it.sizeCompare(size) < 0 /** Tests if the size of the collection is less than or equal to some value. */ @@ -887,22 +895,22 @@ object IterableOps { */ @SerialVersionUID(3L) class WithFilter[+A, +CC[_]]( - self: IterableOps[A, CC, _], + self: IterableOps[A, CC, _]^, p: A => Boolean ) extends collection.WithFilter[A, CC] with Serializable { - protected def filtered: Iterable[A] = + protected def filtered: Iterable[A]^{this} = new View.Filter(self, p, isFlipped = false) - def map[B](f: A => B): CC[B] = + def map[B](f: A => B): CC[B]^{this, f} = self.iterableFactory.from(new View.Map(filtered, f)) - def flatMap[B](f: A => IterableOnce[B]): CC[B] = + def flatMap[B](f: A => IterableOnce[B]^): CC[B]^{this, f} = self.iterableFactory.from(new View.FlatMap(filtered, f)) def foreach[U](f: A => U): Unit = filtered.foreach(f) - def withFilter(q: A => Boolean): WithFilter[A, CC] = + def withFilter(q: A => Boolean): WithFilter[A, CC]^{this, q} = new WithFilter(self, (a: A) => p(a) && q(a)) } @@ -916,16 +924,16 @@ object Iterable extends IterableFactory.Delegate[Iterable](immutable.Iterable) { override def iterator = Iterator.single(a) override def knownSize = 1 override def head = a - override def headOption: Some[A] = Some(a) + override def headOption = Some(a) override def last = a - override def lastOption: Some[A] = Some(a) - override def view: View.Single[A] = new View.Single(a) + override def lastOption = Some(a) + override def view = new View.Single(a) override def take(n: Int) = if (n > 0) this else Iterable.empty override def takeRight(n: Int) = if (n > 0) this else Iterable.empty override def drop(n: Int) = if (n > 0) Iterable.empty else this override def dropRight(n: Int) = if (n > 0) Iterable.empty else this - override def tail: Iterable[Nothing] = Iterable.empty - override def init: Iterable[Nothing] = Iterable.empty + override def tail = Iterable.empty + override def init = Iterable.empty } } @@ -940,7 +948,7 @@ abstract class AbstractIterable[+A] extends Iterable[A] * same as `C`. */ trait IterableFactoryDefaults[+A, +CC[x] <: IterableOps[x, CC, CC[x]]] extends IterableOps[A, CC, CC[A @uncheckedVariance]] { - protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]): CC[A @uncheckedVariance] = iterableFactory.from(coll) + protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]^): CC[A @uncheckedVariance]^{coll} = iterableFactory.from(coll) protected def newSpecificBuilder: Builder[A @uncheckedVariance, CC[A @uncheckedVariance]] = iterableFactory.newBuilder[A] // overridden for efficiency, since we know CC[A] =:= C @@ -958,7 +966,7 @@ trait IterableFactoryDefaults[+A, +CC[x] <: IterableOps[x, CC, CC[x]]] extends I trait EvidenceIterableFactoryDefaults[+A, +CC[x] <: IterableOps[x, CC, CC[x]], Ev[_]] extends IterableOps[A, CC, CC[A @uncheckedVariance]] { protected def evidenceIterableFactory: EvidenceIterableFactory[CC, Ev] implicit protected def iterableEvidence: Ev[A @uncheckedVariance] - override protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]): CC[A @uncheckedVariance] = evidenceIterableFactory.from(coll) + override protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]^): CC[A @uncheckedVariance]^{coll} = evidenceIterableFactory.from(coll) override protected def newSpecificBuilder: Builder[A @uncheckedVariance, CC[A @uncheckedVariance]] = evidenceIterableFactory.newBuilder[A] override def empty: CC[A @uncheckedVariance] = evidenceIterableFactory.empty } @@ -980,11 +988,11 @@ trait SortedSetFactoryDefaults[+A, +WithFilterCC[x] <: IterableOps[x, WithFilterCC, WithFilterCC[x]] with Set[x]] extends SortedSetOps[A @uncheckedVariance, CC, CC[A @uncheckedVariance]] { self: IterableOps[A, WithFilterCC, _] => - override protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]): CC[A @uncheckedVariance] = sortedIterableFactory.from(coll)(ordering) + override protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]^): CC[A @uncheckedVariance]^{coll} = sortedIterableFactory.from(coll)(ordering) override protected def newSpecificBuilder: mutable.Builder[A @uncheckedVariance, CC[A @uncheckedVariance]] = sortedIterableFactory.newBuilder[A](ordering) override def empty: CC[A @uncheckedVariance] = sortedIterableFactory.empty(ordering) - override def withFilter(p: A => Boolean): SortedSetOps.WithFilter[A, WithFilterCC, CC] = + override def withFilter(p: A => Boolean): SortedSetOps.WithFilter[A, WithFilterCC, CC]^{p} = new SortedSetOps.WithFilter[A, WithFilterCC, CC](this, p) } @@ -1004,7 +1012,8 @@ trait SortedSetFactoryDefaults[+A, trait MapFactoryDefaults[K, +V, +CC[x, y] <: IterableOps[(x, y), Iterable, Iterable[(x, y)]], +WithFilterCC[x] <: IterableOps[x, WithFilterCC, WithFilterCC[x]] with Iterable[x]] extends MapOps[K, V, CC, CC[K, V @uncheckedVariance]] with IterableOps[(K, V), WithFilterCC, CC[K, V @uncheckedVariance]] { - override protected def fromSpecific(coll: IterableOnce[(K, V @uncheckedVariance)]): CC[K, V @uncheckedVariance] = mapFactory.from(coll) + this: MapFactoryDefaults[K, V, CC, WithFilterCC] => + override protected def fromSpecific(coll: IterableOnce[(K, V @uncheckedVariance)]^): CC[K, V @uncheckedVariance]^{coll} = mapFactory.from(coll) override protected def newSpecificBuilder: mutable.Builder[(K, V @uncheckedVariance), CC[K, V @uncheckedVariance]] = mapFactory.newBuilder[K, V] override def empty: CC[K, V @uncheckedVariance] = (this: AnyRef) match { // Implemented here instead of in TreeSeqMap since overriding empty in TreeSeqMap is not forwards compatible (should be moved) @@ -1012,7 +1021,7 @@ trait MapFactoryDefaults[K, +V, case _ => mapFactory.empty } - override def withFilter(p: ((K, V)) => Boolean): MapOps.WithFilter[K, V, WithFilterCC, CC] = + override def withFilter(p: ((K, V)) => Boolean): MapOps.WithFilter[K, V, WithFilterCC, CC]^{p} = new MapOps.WithFilter[K, V, WithFilterCC, CC](this, p) } @@ -1035,9 +1044,9 @@ trait SortedMapFactoryDefaults[K, +V, self: IterableOps[(K, V), WithFilterCC, _] => override def empty: CC[K, V @uncheckedVariance] = sortedMapFactory.empty(ordering) - override protected def fromSpecific(coll: IterableOnce[(K, V @uncheckedVariance)]): CC[K, V @uncheckedVariance] = sortedMapFactory.from(coll)(ordering) + override protected def fromSpecific(coll: IterableOnce[(K, V @uncheckedVariance)]^): CC[K, V @uncheckedVariance]^{coll} = sortedMapFactory.from(coll)(ordering) override protected def newSpecificBuilder: mutable.Builder[(K, V @uncheckedVariance), CC[K, V @uncheckedVariance]] = sortedMapFactory.newBuilder[K, V](ordering) - override def withFilter(p: ((K, V)) => Boolean): collection.SortedMapOps.WithFilter[K, V, WithFilterCC, UnsortedCC, CC] = + override def withFilter(p: ((K, V)) => Boolean): collection.SortedMapOps.WithFilter[K, V, WithFilterCC, UnsortedCC, CC]^{p} = new collection.SortedMapOps.WithFilter[K, V, WithFilterCC, UnsortedCC, CC](this, p) } diff --git a/scala2-library-cc/src/scala/collection/IterableOnce.scala b/scala2-library-cc/src/scala/collection/IterableOnce.scala index 70d95da028b0..30eb142ae156 100644 --- a/scala2-library-cc/src/scala/collection/IterableOnce.scala +++ b/scala2-library-cc/src/scala/collection/IterableOnce.scala @@ -20,6 +20,7 @@ import scala.language.implicitConversions import scala.math.{Numeric, Ordering} import scala.reflect.ClassTag import scala.runtime.{AbstractFunction1, AbstractFunction2} +import language.experimental.captureChecking /** * A template trait for collections which can be traversed either once only @@ -42,8 +43,10 @@ import scala.runtime.{AbstractFunction1, AbstractFunction2} * @define coll collection */ trait IterableOnce[+A] extends Any { + this: IterableOnce[A]^ => + /** Iterator can be used only once */ - def iterator: Iterator[A] + def iterator: Iterator[A]^{this} /** Returns a [[scala.collection.Stepper]] for the elements of this collection. * @@ -65,9 +68,9 @@ trait IterableOnce[+A] extends Any { * allow creating parallel streams, whereas bare Steppers can be converted only to sequential * streams. */ - def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S = { + def stepper[S <: Stepper[_]^{this}](implicit shape: StepperShape[A, S]): S = { import convert.impl._ - val s = shape.shape match { + val s: Any = shape.shape match { case StepperShape.IntShape => new IntIteratorStepper (iterator.asInstanceOf[Iterator[Int]]) case StepperShape.LongShape => new LongIteratorStepper (iterator.asInstanceOf[Iterator[Long]]) case StepperShape.DoubleShape => new DoubleIteratorStepper(iterator.asInstanceOf[Iterator[Double]]) @@ -84,7 +87,7 @@ trait IterableOnce[+A] extends Any { final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) extends AnyVal { @deprecated("Use .iterator.withFilter(...) instead", "2.13.0") - def withFilter(f: A => Boolean): Iterator[A] = it.iterator.withFilter(f) + def withFilter(f: A => Boolean): Iterator[A]^{f} = it.iterator.withFilter(f) @deprecated("Use .iterator.reduceLeftOption(...) instead", "2.13.0") def reduceLeftOption(f: (A, A) => A): Option[A] = it.iterator.reduceLeftOption(f) @@ -102,7 +105,7 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext def reduceRight(f: (A, A) => A): A = it.iterator.reduceRight(f) @deprecated("Use .iterator.maxBy(...) instead", "2.13.0") - def maxBy[B](f: A => B)(implicit cmp: Ordering[B]): A = it.iterator.maxBy(f) + def maxBy[B](f: A -> B)(implicit cmp: Ordering[B]): A = it.iterator.maxBy(f) @deprecated("Use .iterator.reduceLeft(...) instead", "2.13.0") def reduceLeft(f: (A, A) => A): A = it.iterator.reduceLeft(f) @@ -120,7 +123,7 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext def reduceOption(f: (A, A) => A): Option[A] = it.iterator.reduceOption(f) @deprecated("Use .iterator.minBy(...) instead", "2.13.0") - def minBy[B](f: A => B)(implicit cmp: Ordering[B]): A = it.iterator.minBy(f) + def minBy[B](f: A -> B)(implicit cmp: Ordering[B]): A = it.iterator.minBy(f) @deprecated("Use .iterator.size instead", "2.13.0") def size: Int = it.iterator.size @@ -132,7 +135,7 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext def collectFirst[B](f: PartialFunction[A, B]): Option[B] = it.iterator.collectFirst(f) @deprecated("Use .iterator.filter(...) instead", "2.13.0") - def filter(f: A => Boolean): Iterator[A] = it.iterator.filter(f) + def filter(f: A => Boolean): Iterator[A]^{f} = it.iterator.filter(f) @deprecated("Use .iterator.exists(...) instead", "2.13.0") def exists(f: A => Boolean): Boolean = it.iterator.exists(f) @@ -238,13 +241,13 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext @`inline` def :\ [B](z: B)(op: (A, B) => B): B = foldRight[B](z)(op) @deprecated("Use .iterator.map instead or consider requiring an Iterable", "2.13.0") - def map[B](f: A => B): IterableOnce[B] = it match { + def map[B](f: A => B): IterableOnce[B]^{f} = it match { case it: Iterable[A] => it.map(f) case _ => it.iterator.map(f) } @deprecated("Use .iterator.flatMap instead or consider requiring an Iterable", "2.13.0") - def flatMap[B](f: A => IterableOnce[B]): IterableOnce[B] = it match { + def flatMap[B](f: A => IterableOnce[B]^): IterableOnce[B]^{f} = it match { case it: Iterable[A] => it.flatMap(f) case _ => it.iterator.flatMap(f) } @@ -269,10 +272,11 @@ object IterableOnce { math.max(math.min(math.min(len, srcLen), destLen - start), 0) /** Calls `copyToArray` on the given collection, regardless of whether or not it is an `Iterable`. */ - @inline private[collection] def copyElemsToArray[A, B >: A](elems: IterableOnce[A], - xs: Array[B], - start: Int = 0, - len: Int = Int.MaxValue): Int = + @inline private[collection] def copyElemsToArray[A, B >: A]( + elems: IterableOnce[A]^, + xs: Array[B], + start: Int = 0, + len: Int = Int.MaxValue): Int = elems match { case src: Iterable[A] => src.copyToArray[B](xs, start, len) case src => src.iterator.copyToArray[B](xs, start, len) @@ -315,9 +319,11 @@ object IterableOnce { * @define coll collection * */ -trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => +trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => /////////////////////////////////////////////////////////////// Abstract methods that must be implemented + import IterableOnceOps.Maximized + /** Produces a $coll containing cumulative results of applying the * operator going left to right, including the initial value. * @@ -329,7 +335,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @param op the binary operator applied to the intermediate result and the element * @return collection with intermediate results */ - def scanLeft[B](z: B)(op: (B, A) => B): CC[B] + def scanLeft[B](z: B)(op: (B, A) => B): CC[B]^{this, op} /** Selects all elements of this $coll which satisfy a predicate. * @@ -337,7 +343,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return a new $coll consisting of all elements of this $coll that satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filter(p: A => Boolean): C + def filter(p: A => Boolean): C^{this, p} /** Selects all elements of this $coll which do not satisfy a predicate. * @@ -345,7 +351,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return a new $coll consisting of all elements of this $coll that do not satisfy the given * predicate `pred`. Their order may not be preserved. */ - def filterNot(pred: A => Boolean): C + def filterNot(p: A => Boolean): C^{this, p} /** Selects the first ''n'' elements. * $orderDependent @@ -354,7 +360,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * or else the whole $coll, if it has less than `n` elements. * If `n` is negative, returns an empty $coll. */ - def take(n: Int): C + def take(n: Int): C^{this} /** Takes longest prefix of elements that satisfy a predicate. * $orderDependent @@ -362,7 +368,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return the longest prefix of this $coll whose elements all satisfy * the predicate `p`. */ - def takeWhile(p: A => Boolean): C + def takeWhile(p: A => Boolean): C^{this, p} /** Selects all elements except first ''n'' ones. * $orderDependent @@ -371,7 +377,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * empty $coll, if this $coll has less than `n` elements. * If `n` is negative, don't drop any elements. */ - def drop(n: Int): C + def drop(n: Int): C^{this} /** Drops longest prefix of elements that satisfy a predicate. * $orderDependent @@ -379,7 +385,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return the longest suffix of this $coll whose first element * does not satisfy the predicate `p`. */ - def dropWhile(p: A => Boolean): C + def dropWhile(p: A => Boolean): C^{this, p} /** Selects an interval of elements. The returned $coll is made up * of all elements `x` which satisfy the invariant: @@ -394,7 +400,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * index `from` extending up to (but not including) index `until` * of this $coll. */ - def slice(from: Int, until: Int): C + def slice(from: Int, until: Int): C^{this} /** Builds a new $coll by applying a function to all elements of this $coll. * @@ -403,7 +409,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return a new $coll resulting from applying the given function * `f` to each element of this $coll and collecting the results. */ - def map[B](f: A => B): CC[B] + def map[B](f: A => B): CC[B]^{this, f} /** Builds a new $coll by applying a function to all elements of this $coll * and using the elements of the resulting collections. @@ -436,7 +442,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return a new $coll resulting from applying the given collection-valued function * `f` to each element of this $coll and concatenating the results. */ - def flatMap[B](f: A => IterableOnce[B]): CC[B] + def flatMap[B](f: A => IterableOnce[B]^): CC[B]^{this, f} /** Converts this $coll of iterable collections into * a $coll formed by the elements of these iterable @@ -464,7 +470,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * type of this $coll is an `Iterable`. * @return a new $coll resulting from concatenating all element ${coll}s. */ - def flatten[B](implicit asIterable: A => IterableOnce[B]): CC[B] + def flatten[B](implicit asIterable: A -> IterableOnce[B]): CC[B]^{this} /** Builds a new $coll by applying a partial function to all elements of this $coll * on which the function is defined. @@ -475,7 +481,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * `pf` to each element on which it is defined and collecting the results. * The order of the elements is preserved. */ - def collect[B](pf: PartialFunction[A, B]): CC[B] + def collect[B](pf: PartialFunction[A, B]^): CC[B]^{this, pf} /** Zips this $coll with its indices. * @@ -484,7 +490,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @example * `List("a", "b", "c").zipWithIndex == List(("a", 0), ("b", 1), ("c", 2))` */ - def zipWithIndex: CC[(A @uncheckedVariance, Int)] + def zipWithIndex: CC[(A @uncheckedVariance, Int)]^{this} /** Splits this $coll into a prefix/suffix pair according to a predicate. * @@ -497,7 +503,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return a pair consisting of the longest prefix of this $coll whose * elements all satisfy `p`, and the rest of this $coll. */ - def span(p: A => Boolean): (C, C) + def span(p: A => Boolean): (C^{this, p}, C^{this, p}) /** Splits this $coll into a prefix/suffix pair at a given position. * @@ -509,7 +515,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return a pair of ${coll}s consisting of the first `n` * elements of this $coll, and the other elements. */ - def splitAt(n: Int): (C, C) = { + def splitAt(n: Int): (C^{this}, C^{this}) = { class Spanner extends runtime.AbstractFunction1[A, Boolean] { var i = 0 def apply(a: A) = i < n && { i += 1 ; true } @@ -527,7 +533,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @tparam U the return type of f * @return The same logical collection as this */ - def tapEach[U](f: A => U): C + def tapEach[U](f: A => U): C^{this, f} /////////////////////////////////////////////////////////////// Concrete methods based on iterator @@ -802,7 +808,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => case _ => Some(reduceLeft(op)) } private final def reduceLeftOptionIterator[B >: A](op: (B, A) => B): Option[B] = reduceOptionIterator[A, B](iterator)(op) - private final def reduceOptionIterator[X >: A, B >: X](it: Iterator[X])(op: (B, X) => B): Option[B] = { + private final def reduceOptionIterator[X >: A, B >: X](it: Iterator[X]^)(op: (B, X) => B): Option[B] = { if (it.hasNext) { var acc: B = it.next() while (it.hasNext) @@ -1041,35 +1047,12 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return the first element of this $coll with the largest value measured by function f * with respect to the ordering `cmp`. */ - def maxBy[B](f: A => B)(implicit ord: Ordering[B]): A = + def maxBy[B](f: A -> B)(implicit ord: Ordering[B]): A = knownSize match { case 0 => throw new UnsupportedOperationException("empty.maxBy") case _ => foldLeft(new Maximized[A, B]("maxBy")(f)(ord.gt))((m, a) => m(m, a)).result } - private class Maximized[X, B](descriptor: String)(f: X => B)(cmp: (B, B) => Boolean) extends AbstractFunction2[Maximized[X, B], X, Maximized[X, B]] { - var maxElem: X = null.asInstanceOf[X] - var maxF: B = null.asInstanceOf[B] - var nonEmpty = false - def toOption: Option[X] = if (nonEmpty) Some(maxElem) else None - def result: X = if (nonEmpty) maxElem else throw new UnsupportedOperationException(s"empty.$descriptor") - def apply(m: Maximized[X, B], a: X): Maximized[X, B] = - if (m.nonEmpty) { - val fa = f(a) - if (cmp(fa, maxF)) { - maxF = fa - maxElem = a - } - m - } - else { - m.nonEmpty = true - m.maxElem = a - m.maxF = f(a) - m - } - } - /** Finds the first element which yields the largest value measured by function f. * * $willNotTerminateInf @@ -1080,7 +1063,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return an option value containing the first element of this $coll with the * largest value measured by function f with respect to the ordering `cmp`. */ - def maxByOption[B](f: A => B)(implicit ord: Ordering[B]): Option[A] = + def maxByOption[B](f: A -> B)(implicit ord: Ordering[B]): Option[A] = knownSize match { case 0 => None case _ => foldLeft(new Maximized[A, B]("maxBy")(f)(ord.gt))((m, a) => m(m, a)).toOption @@ -1097,7 +1080,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @return the first element of this $coll with the smallest value measured by function f * with respect to the ordering `cmp`. */ - def minBy[B](f: A => B)(implicit ord: Ordering[B]): A = + def minBy[B](f: A -> B)(implicit ord: Ordering[B]): A = knownSize match { case 0 => throw new UnsupportedOperationException("empty.minBy") case _ => foldLeft(new Maximized[A, B]("minBy")(f)(ord.lt))((m, a) => m(m, a)).result @@ -1114,7 +1097,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * with the smallest value measured by function f * with respect to the ordering `cmp`. */ - def minByOption[B](f: A => B)(implicit ord: Ordering[B]): Option[A] = + def minByOption[B](f: A -> B)(implicit ord: Ordering[B]): Option[A] = knownSize match { case 0 => None case _ => foldLeft(new Maximized[A, B]("minBy")(f)(ord.lt))((m, a) => m(m, a)).toOption @@ -1310,7 +1293,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => def to[C1](factory: Factory[A, C1]): C1 = factory.fromSpecific(this) @deprecated("Use .iterator instead of .toIterator", "2.13.0") - @`inline` final def toIterator: Iterator[A] = iterator + @`inline` final def toIterator: Iterator[A]^{this} = iterator def toList: immutable.List[A] = immutable.List.from(this) @@ -1328,9 +1311,9 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => def toIndexedSeq: immutable.IndexedSeq[A] = immutable.IndexedSeq.from(this) @deprecated("Use .to(LazyList) instead of .toStream", "2.13.0") - @inline final def toStream: immutable.Stream[A] = to(immutable.Stream) + @`inline` final def toStream: immutable.Stream[A] = to(immutable.Stream) - @inline final def toBuffer[B >: A]: mutable.Buffer[B] = mutable.Buffer.from(this) + @`inline` final def toBuffer[B >: A]: mutable.Buffer[B] = mutable.Buffer.from(this) /** Convert collection to array. * @@ -1353,3 +1336,31 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => xs } } + +object IterableOnceOps: + + // Moved out of trait IterableOnceOps to here, since universal traits cannot + // have nested classes in Scala 3 + private class Maximized[X, B](descriptor: String)(f: X -> B)(cmp: (B, B) -> Boolean) extends AbstractFunction2[Maximized[X, B], X, Maximized[X, B]] { + var maxElem: X = null.asInstanceOf[X] + var maxF: B = null.asInstanceOf[B] + var nonEmpty = false + def toOption: Option[X] = if (nonEmpty) Some(maxElem) else None + def result: X = if (nonEmpty) maxElem else throw new UnsupportedOperationException(s"empty.$descriptor") + def apply(m: Maximized[X, B], a: X): Maximized[X, B] = + if (m.nonEmpty) { + val fa = f(a) + if (cmp(fa, maxF)) { + maxF = fa + maxElem = a + } + m + } + else { + m.nonEmpty = true + m.maxElem = a + m.maxF = f(a) + m + } + } +end IterableOnceOps diff --git a/scala2-library-cc/src/scala/collection/Iterator.scala b/scala2-library-cc/src/scala/collection/Iterator.scala index 14c51732afea..57a12767320a 100644 --- a/scala2-library-cc/src/scala/collection/Iterator.scala +++ b/scala2-library-cc/src/scala/collection/Iterator.scala @@ -16,6 +16,8 @@ import scala.collection.mutable.{ArrayBuffer, ArrayBuilder, Builder, ImmutableBu import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance import scala.runtime.Statics +import language.experimental.captureChecking + /** Iterators are data structures that allow to iterate over a sequence * of elements. They have a `hasNext` method for checking @@ -71,7 +73,8 @@ import scala.runtime.Statics * iterators as well. * @define coll iterator */ -trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Iterator[A]] { self => +trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Iterator[A]] { + self: Iterator[A]^ => /** Check if there is a next element available. * @@ -93,7 +96,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite @throws[NoSuchElementException] def next(): A - @inline final def iterator = this + @inline final def iterator: Iterator[A]^{this} = this /** Wraps the value of `next()` in an option. * @@ -117,7 +120,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * @return a buffered iterator producing the same values as this iterator. * @note Reuse: $consumesAndProducesIterator */ - def buffered: BufferedIterator[A] = new AbstractIterator[A] with BufferedIterator[A] { + def buffered: BufferedIterator[A]^{this} = new AbstractIterator[A] with BufferedIterator[A] { private[this] var hd: A = _ private[this] var hdDefined: Boolean = false @@ -153,7 +156,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * A `GroupedIterator` is yielded by `grouped` and by `sliding`, * where the `step` may differ from the group `size`. */ - class GroupedIterator[B >: A](self: Iterator[B], size: Int, step: Int) extends AbstractIterator[immutable.Seq[B]] { + class GroupedIterator[B >: A](self: Iterator[B]^, size: Int, step: Int) extends AbstractIterator[immutable.Seq[B]] { require(size >= 1 && step >= 1, f"size=$size%d and step=$step%d, but both must be positive") @@ -162,7 +165,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite private[this] var first = true // if !first, advancing may skip ahead private[this] var filled = false // whether the buffer is "hot" private[this] var partial = true // whether to emit partial sequence - private[this] var padding: () => B = null // what to pad short sequences with + private[this] var padding: () -> B = null // what to pad short sequences with private[this] def pad = padding != null // irrespective of partial flag private[this] def newBuilder = { val b = ArrayBuilder.make[Any] @@ -185,7 +188,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * @note This method is mutually exclusive with `withPartial`. * @group Configuration */ - def withPadding(x: => B): this.type = { + def withPadding(x: -> B): this.type = { padding = () => x partial = true // redundant, as padding always results in complete segment this @@ -291,7 +294,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * all elements of this $coll followed by the minimal number of occurrences of `elem` so * that the resulting collection has a length of at least `len`. */ - def padTo[B >: A](len: Int, elem: B): Iterator[B] = new AbstractIterator[B] { + def padTo[B >: A](len: Int, elem: B): Iterator[B]^{this} = new AbstractIterator[B] { private[this] var i = 0 override def knownSize: Int = { @@ -321,7 +324,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * is the same as in the original iterator. * @note Reuse: $consumesOneAndProducesTwoIterators */ - def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = { + def partition(p: A => Boolean): (Iterator[A]^{this, p}, Iterator[A]^{this, p}) = { val (a, b) = duplicate (a filter p, b filterNot p) } @@ -341,7 +344,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * * @note Reuse: $consumesAndProducesIterator */ - def grouped[B >: A](size: Int): GroupedIterator[B] = + def grouped[B >: A](size: Int): GroupedIterator[B]^{this} = new GroupedIterator[B](self, size, size) /** Returns an iterator which presents a "sliding window" view of @@ -377,13 +380,13 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * * @note Reuse: $consumesAndProducesIterator */ - def sliding[B >: A](size: Int, step: Int = 1): GroupedIterator[B] = + def sliding[B >: A](size: Int, step: Int = 1): GroupedIterator[B]^{this} = new GroupedIterator[B](self, size, step) - def scanLeft[B](z: B)(op: (B, A) => B): Iterator[B] = new AbstractIterator[B] { + def scanLeft[B](z: B)(op: (B, A) => B): Iterator[B]^{this, op} = new AbstractIterator[B] { // We use an intermediate iterator that iterates through the first element `z` // and then that will be modified to iterate through the collection - private[this] var current: Iterator[B] = + private[this] var current: Iterator[B]^{self, op} = new AbstractIterator[B] { override def knownSize = { val thisSize = self.knownSize @@ -412,7 +415,8 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite } @deprecated("Call scanRight on an Iterable instead.", "2.13.0") - def scanRight[B](z: B)(op: (A, B) => B): Iterator[B] = ArrayBuffer.from(this).scanRight(z)(op).iterator + def scanRight[B](z: B)(op: (A, B) => B): Iterator[B]^{this} = + ArrayBuffer.from[A](this).scanRight(z)(op).iterator def indexWhere(p: A => Boolean, from: Int = 0): Int = { var i = math.max(from, 0) @@ -465,11 +469,11 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite @deprecatedOverriding("isEmpty is defined as !hasNext; override hasNext instead", "2.13.0") override def isEmpty: Boolean = !hasNext - def filter(p: A => Boolean): Iterator[A] = filterImpl(p, isFlipped = false) + def filter(p: A => Boolean): Iterator[A]^{this, p} = filterImpl(p, isFlipped = false) - def filterNot(p: A => Boolean): Iterator[A] = filterImpl(p, isFlipped = true) + def filterNot(p: A => Boolean): Iterator[A]^{this, p} = filterImpl(p, isFlipped = true) - private[collection] def filterImpl(p: A => Boolean, isFlipped: Boolean): Iterator[A] = new AbstractIterator[A] { + private[collection] def filterImpl(p: A => Boolean, isFlipped: Boolean): Iterator[A]^{this, p} = new AbstractIterator[A] { private[this] var hd: A = _ private[this] var hdDefined: Boolean = false @@ -479,9 +483,9 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite while (p(hd) == isFlipped) { if (!self.hasNext) return false hd = self.next() - } + } hdDefined = true - true + true } def next() = @@ -503,9 +507,9 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * @return an iterator which produces those values of this iterator which satisfy the predicate `p`. * @note Reuse: $consumesAndProducesIterator */ - def withFilter(p: A => Boolean): Iterator[A] = filter(p) + def withFilter(p: A => Boolean): Iterator[A]^{this, p} = filter(p) - def collect[B](pf: PartialFunction[A, B]): Iterator[B] = new AbstractIterator[B] with (A => B) { + def collect[B](pf: PartialFunction[A, B]^): Iterator[B]^{this, pf} = new AbstractIterator[B] with (A -> B) { // Manually buffer to avoid extra layer of wrapping with buffered private[this] var hd: B = _ @@ -541,7 +545,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * * @note Reuse: $consumesIterator */ - def distinct: Iterator[A] = distinctBy(identity) + def distinct: Iterator[A]^{this} = distinctBy(identity) /** * Builds a new iterator from this one without any duplicated elements as determined by `==` after applying @@ -553,7 +557,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * * @note Reuse: $consumesIterator */ - def distinctBy[B](f: A => B): Iterator[A] = new AbstractIterator[A] { + def distinctBy[B](f: A -> B): Iterator[A]^{this} = new AbstractIterator[A] { private[this] val traversedValues = mutable.HashSet.empty[B] private[this] var nextElementDefined: Boolean = false @@ -578,14 +582,14 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite } } - def map[B](f: A => B): Iterator[B] = new AbstractIterator[B] { + def map[B](f: A => B): Iterator[B]^{this, f} = new AbstractIterator[B] { override def knownSize = self.knownSize def hasNext = self.hasNext def next() = f(self.next()) } - def flatMap[B](f: A => IterableOnce[B]): Iterator[B] = new AbstractIterator[B] { - private[this] var cur: Iterator[B] = Iterator.empty + def flatMap[B](f: A => IterableOnce[B]^): Iterator[B]^{this, f} = new AbstractIterator[B] { + private[this] var cur: Iterator[B]^{f} = Iterator.empty /** Trillium logic boolean: -1 = unknown, 0 = false, 1 = true */ private[this] var _hasNext: Int = -1 @@ -619,19 +623,19 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite } } - def flatten[B](implicit ev: A => IterableOnce[B]): Iterator[B] = + def flatten[B](implicit ev: A -> IterableOnce[B]): Iterator[B]^{this} = flatMap[B](ev) - def concat[B >: A](xs: => IterableOnce[B]): Iterator[B] = new Iterator.ConcatIterator[B](self).concat(xs) + def concat[B >: A](xs: => IterableOnce[B]^): Iterator[B]^{this, xs} = new Iterator.ConcatIterator[B](self).concat(xs) - @`inline` final def ++ [B >: A](xs: => IterableOnce[B]): Iterator[B] = concat(xs) + @`inline` final def ++ [B >: A](xs: => IterableOnce[B]^): Iterator[B]^{this, xs} = concat(xs) - def take(n: Int): Iterator[A] = sliceIterator(0, n max 0) + def take(n: Int): Iterator[A]^{this} = sliceIterator(0, n max 0) - def takeWhile(p: A => Boolean): Iterator[A] = new AbstractIterator[A] { + def takeWhile(p: A => Boolean): Iterator[A]^{self, p} = new AbstractIterator[A] { private[this] var hd: A = _ private[this] var hdDefined: Boolean = false - private[this] var tail: Iterator[A] = self + private[this] var tail: Iterator[A]^{self} = self def hasNext = hdDefined || tail.hasNext && { hd = tail.next() @@ -642,9 +646,9 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite def next() = if (hasNext) { hdDefined = false; hd } else Iterator.empty.next() } - def drop(n: Int): Iterator[A] = sliceIterator(n, -1) + def drop(n: Int): Iterator[A]^{this} = sliceIterator(n, -1) - def dropWhile(p: A => Boolean): Iterator[A] = new AbstractIterator[A] { + def dropWhile(p: A => Boolean): Iterator[A]^{this, p} = new AbstractIterator[A] { // Magic value: -1 = hasn't dropped, 0 = found first, 1 = defer to parent iterator private[this] var status = -1 // Local buffering to avoid double-wrap with .buffered @@ -680,7 +684,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * * @note Reuse: $consumesOneAndProducesTwoIterators */ - def span(p: A => Boolean): (Iterator[A], Iterator[A]) = { + def span(p: A => Boolean): (Iterator[A]^{this, p}, Iterator[A]^{this, p}) = { /* * Giving a name to following iterator (as opposed to trailing) because * anonymous class is represented as a structural type that trailing @@ -779,10 +783,10 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite (leading, trailing) } - def slice(from: Int, until: Int): Iterator[A] = sliceIterator(from, until max 0) + def slice(from: Int, until: Int): Iterator[A]^{this} = sliceIterator(from, until max 0) /** Creates an optionally bounded slice, unbounded if `until` is negative. */ - protected def sliceIterator(from: Int, until: Int): Iterator[A] = { + protected def sliceIterator(from: Int, until: Int): Iterator[A]^{this} = { val lo = from max 0 val rest = if (until < 0) -1 // unbounded @@ -793,14 +797,14 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite else new Iterator.SliceIterator(this, lo, rest) } - def zip[B](that: IterableOnce[B]): Iterator[(A, B)] = new AbstractIterator[(A, B)] { + def zip[B](that: IterableOnce[B]^): Iterator[(A, B)]^{this, that} = new AbstractIterator[(A, B)] { val thatIterator = that.iterator override def knownSize = self.knownSize min thatIterator.knownSize def hasNext = self.hasNext && thatIterator.hasNext def next() = (self.next(), thatIterator.next()) } - def zipAll[A1 >: A, B](that: IterableOnce[B], thisElem: A1, thatElem: B): Iterator[(A1, B)] = new AbstractIterator[(A1, B)] { + def zipAll[A1 >: A, B](that: IterableOnce[B]^, thisElem: A1, thatElem: B): Iterator[(A1, B)]^{this, that} = new AbstractIterator[(A1, B)] { val thatIterator = that.iterator override def knownSize = { val thisSize = self.knownSize @@ -817,7 +821,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite } } - def zipWithIndex: Iterator[(A, Int)] = new AbstractIterator[(A, Int)] { + def zipWithIndex: Iterator[(A, Int)]^{this} = new AbstractIterator[(A, Int)] { var idx = 0 override def knownSize = self.knownSize def hasNext = self.hasNext @@ -837,7 +841,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * * @inheritdoc */ - def sameElements[B >: A](that: IterableOnce[B]): Boolean = { + def sameElements[B >: A](that: IterableOnce[B]^): Boolean = { val those = that.iterator while (hasNext && those.hasNext) if (next() != those.next()) @@ -860,9 +864,9 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * iterated by one iterator but not yet by the other. * @note Reuse: $consumesOneAndProducesTwoIterators */ - def duplicate: (Iterator[A], Iterator[A]) = { + def duplicate: (Iterator[A]^{this}, Iterator[A]^{this}) = { val gap = new scala.collection.mutable.Queue[A] - var ahead: Iterator[A] = null + var ahead: Iterator[A] = null // ahead is captured by Partner, so A is not recognized as parametric class Partner extends AbstractIterator[A] { override def knownSize: Int = self.synchronized { val thisSize = self.knownSize @@ -904,7 +908,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * @param replaced The number of values in the original iterator that are replaced by the patch. * @note Reuse: $consumesTwoAndProducesOneIterator */ - def patch[B >: A](from: Int, patchElems: Iterator[B], replaced: Int): Iterator[B] = + def patch[B >: A](from: Int, patchElems: Iterator[B]^, replaced: Int): Iterator[B]^{this, patchElems} = new AbstractIterator[B] { private[this] var origElems = self // > 0 => that many more elems from `origElems` before switching to `patchElems` @@ -944,7 +948,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite } } - override def tapEach[U](f: A => U): Iterator[A] = new AbstractIterator[A] { + override def tapEach[U](f: A => U): Iterator[A]^{this, f} = new AbstractIterator[A] { override def knownSize = self.knownSize override def hasNext = self.hasNext override def next() = { @@ -972,7 +976,7 @@ object Iterator extends IterableFactory[Iterator] { def hasNext = false def next() = throw new NoSuchElementException("next on empty iterator") override def knownSize: Int = 0 - override protected def sliceIterator(from: Int, until: Int): AbstractIterator[Nothing] = this + override protected def sliceIterator(from: Int, until: Int) = this } /** Creates a target $coll from an existing source collection @@ -981,7 +985,7 @@ object Iterator extends IterableFactory[Iterator] { * @tparam A the type of the collection’s elements * @return a new $coll with the elements of `source` */ - override def from[A](source: IterableOnce[A]): Iterator[A] = source.iterator + override def from[A](source: IterableOnce[A]^): Iterator[A]^{source} = source.iterator /** The iterator which produces no values. */ @`inline` final def empty[T]: Iterator[T] = _empty @@ -1012,7 +1016,7 @@ object Iterator extends IterableFactory[Iterator] { * @param elem the element computation * @return An iterator that produces the results of `n` evaluations of `elem`. */ - override def fill[A](len: Int)(elem: => A): Iterator[A] = new AbstractIterator[A] { + override def fill[A](len: Int)(elem: => A): Iterator[A]^{elem} = new AbstractIterator[A] { private[this] var i = 0 override def knownSize: Int = (len - i) max 0 def hasNext: Boolean = i < len @@ -1027,7 +1031,7 @@ object Iterator extends IterableFactory[Iterator] { * @param f The function computing element values * @return An iterator that produces the values `f(0), ..., f(n -1)`. */ - override def tabulate[A](end: Int)(f: Int => A): Iterator[A] = new AbstractIterator[A] { + override def tabulate[A](end: Int)(f: Int => A): Iterator[A]^{f} = new AbstractIterator[A] { private[this] var i = 0 override def knownSize: Int = (end - i) max 0 def hasNext: Boolean = i < end @@ -1100,7 +1104,7 @@ object Iterator extends IterableFactory[Iterator] { * @param f the function that's repeatedly applied * @return the iterator producing the infinite sequence of values `start, f(start), f(f(start)), ...` */ - def iterate[T](start: T)(f: T => T): Iterator[T] = new AbstractIterator[T] { + def iterate[T](start: T)(f: T => T): Iterator[T]^{f} = new AbstractIterator[T] { private[this] var first = true private[this] var acc = start def hasNext: Boolean = true @@ -1122,7 +1126,7 @@ object Iterator extends IterableFactory[Iterator] { * @tparam S Type of the internal state * @return an Iterator that produces elements using `f` until `f` returns `None` */ - override def unfold[A, S](init: S)(f: S => Option[(A, S)]): Iterator[A] = new UnfoldIterator(init)(f) + override def unfold[A, S](init: S)(f: S => Option[(A, S)]): Iterator[A]^{f} = new UnfoldIterator(init)(f) /** Creates an infinite-length iterator returning the results of evaluating an expression. * The expression is recomputed for every element. @@ -1130,7 +1134,7 @@ object Iterator extends IterableFactory[Iterator] { * @param elem the element computation. * @return the iterator containing an infinite number of results of evaluating `elem`. */ - def continually[A](elem: => A): Iterator[A] = new AbstractIterator[A] { + def continually[A](elem: => A): Iterator[A]^{elem} = new AbstractIterator[A] { def hasNext = true def next() = elem } @@ -1138,7 +1142,8 @@ object Iterator extends IterableFactory[Iterator] { /** Creates an iterator to which other iterators can be appended efficiently. * Nested ConcatIterators are merged to avoid blowing the stack. */ - private final class ConcatIterator[+A](private var current: Iterator[A @uncheckedVariance]) extends AbstractIterator[A] { + private final class ConcatIterator[+A](val from: Iterator[A]^) extends AbstractIterator[A] { + private var current: Iterator[A]^{from*} = from private var tail: ConcatIteratorCell[A @uncheckedVariance] = null private var last: ConcatIteratorCell[A @uncheckedVariance] = null private var currentHasNextChecked = false @@ -1194,8 +1199,8 @@ object Iterator extends IterableFactory[Iterator] { current.next() } else Iterator.empty.next() - override def concat[B >: A](that: => IterableOnce[B]): Iterator[B] = { - val c = new ConcatIteratorCell[B](that, null).asInstanceOf[ConcatIteratorCell[A]] + override def concat[B >: A](that: => IterableOnce[B]^): Iterator[B]^{this, that} = { + val c: ConcatIteratorCell[A] = new ConcatIteratorCell[B](that, null).asInstanceOf if (tail == null) { tail = c last = c @@ -1209,14 +1214,14 @@ object Iterator extends IterableFactory[Iterator] { } } - private[this] final class ConcatIteratorCell[A](head: => IterableOnce[A], var tail: ConcatIteratorCell[A]) { - def headIterator: Iterator[A] = head.iterator + private[this] final class ConcatIteratorCell[A](head: => IterableOnce[A]^, var tail: ConcatIteratorCell[A]) { + def headIterator: Iterator[A]^{this} = head.iterator // CC todo: can't use {head} as capture set, gives "cannot establish a reference" } /** Creates a delegating iterator capped by a limit count. Negative limit means unbounded. * Lazily skip to start on first evaluation. Avoids daisy-chained iterators due to slicing. */ - private[scala] final class SliceIterator[A](val underlying: Iterator[A], start: Int, limit: Int) extends AbstractIterator[A] { + private[scala] final class SliceIterator[A](val underlying: Iterator[A]^, start: Int, limit: Int) extends AbstractIterator[A] { private[this] var remaining = limit private[this] var dropping = start @inline private def unbounded = remaining < 0 @@ -1247,7 +1252,7 @@ object Iterator extends IterableFactory[Iterator] { else if (unbounded) underlying.next() else empty.next() } - override protected def sliceIterator(from: Int, until: Int): Iterator[A] = { + override protected def sliceIterator(from: Int, until: Int): Iterator[A]^{underlying} = { val lo = from max 0 def adjustedBound = if (unbounded) -1 @@ -1269,7 +1274,7 @@ object Iterator extends IterableFactory[Iterator] { /** Creates an iterator that uses a function `f` to produce elements of * type `A` and update an internal state of type `S`. */ - private final class UnfoldIterator[A, S](init: S)(f: S => Option[(A, S)]) extends AbstractIterator[A] { + private final class UnfoldIterator[A, S](init: S)(f: S => Option[(A, S)])extends AbstractIterator[A] { private[this] var state: S = init private[this] var nextResult: Option[(A, S)] = null @@ -1297,4 +1302,5 @@ object Iterator extends IterableFactory[Iterator] { } /** Explicit instantiation of the `Iterator` trait to reduce class file size in subclasses. */ -abstract class AbstractIterator[+A] extends Iterator[A] +abstract class AbstractIterator[+A] extends Iterator[A]: + this: Iterator[A]^ => diff --git a/scala2-library-cc/src/scala/collection/JavaConverters.scala b/scala2-library-cc/src/scala/collection/JavaConverters.scala index 569e4e8c60a7..69130eae1829 100644 --- a/scala2-library-cc/src/scala/collection/JavaConverters.scala +++ b/scala2-library-cc/src/scala/collection/JavaConverters.scala @@ -17,6 +17,7 @@ import java.{lang => jl, util => ju} import scala.collection.convert._ import scala.language.implicitConversions +import language.experimental.captureChecking /** A variety of decorators that enable converting between * Scala and Java collections using extension methods, `asScala` and `asJava`. diff --git a/scala2-library-cc/src/scala/collection/LazyZipOps.scala b/scala2-library-cc/src/scala/collection/LazyZipOps.scala index 011f62d2380d..1bb4173d219f 100644 --- a/scala2-library-cc/src/scala/collection/LazyZipOps.scala +++ b/scala2-library-cc/src/scala/collection/LazyZipOps.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.implicitConversions +import language.experimental.captureChecking /** Decorator representing lazily zipped pairs. * @@ -21,7 +22,7 @@ import scala.language.implicitConversions * * Note: will not terminate for infinite-sized collections. */ -final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterable[El1], coll2: Iterable[El2]) { +final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterable[El1]^, coll2: Iterable[El2]^) { /** Zips `that` iterable collection with an existing `LazyZip2`. The elements in each collection are * not consumed until a strict operation is invoked on the returned `LazyZip3` decorator. @@ -31,11 +32,11 @@ final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterabl * @return a decorator `LazyZip3` that allows strict operations to be performed on the lazily evaluated tuples or * chained calls to `lazyZip`. Implicit conversion to `Iterable[(El1, El2, B)]` is also supported. */ - def lazyZip[B](that: Iterable[B]): LazyZip3[El1, El2, B, C1] = new LazyZip3(src, coll1, coll2, that) + def lazyZip[B](that: Iterable[B]^): LazyZip3[El1, El2, B, C1]^{this, that} = new LazyZip3(src, coll1, coll2, that) def map[B, C](f: (El1, El2) => B)(implicit bf: BuildFrom[C1, B, C]): C = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator def hasNext = elems1.hasNext && elems2.hasNext @@ -48,7 +49,7 @@ final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterabl def flatMap[B, C](f: (El1, El2) => Iterable[B])(implicit bf: BuildFrom[C1, B, C]): C = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] var _current: Iterator[B] = Iterator.empty @@ -67,7 +68,7 @@ final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterabl def filter[C](p: (El1, El2) => Boolean)(implicit bf: BuildFrom[C1, (El1, El2), C]): C = { bf.fromSpecific(src)(new AbstractView[(El1, El2)] { - def iterator: AbstractIterator[(El1, El2)] = new AbstractIterator[(El1, El2)] { + def iterator = new AbstractIterator[(El1, El2)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] var _current: (El1, El2) = _ @@ -113,7 +114,7 @@ final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterabl } private def toIterable: View[(El1, El2)] = new AbstractView[(El1, El2)] { - def iterator: AbstractIterator[(El1, El2)] = new AbstractIterator[(El1, El2)] { + def iterator = new AbstractIterator[(El1, El2)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator def hasNext = elems1.hasNext && elems2.hasNext @@ -147,9 +148,9 @@ object LazyZip2 { * Note: will not terminate for infinite-sized collections. */ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, - coll1: Iterable[El1], - coll2: Iterable[El2], - coll3: Iterable[El3]) { + coll1: Iterable[El1]^, + coll2: Iterable[El2]^, + coll3: Iterable[El3]^) { /** Zips `that` iterable collection with an existing `LazyZip3`. The elements in each collection are * not consumed until a strict operation is invoked on the returned `LazyZip4` decorator. @@ -159,11 +160,11 @@ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, * @return a decorator `LazyZip4` that allows strict operations to be performed on the lazily evaluated tuples. * Implicit conversion to `Iterable[(El1, El2, El3, B)]` is also supported. */ - def lazyZip[B](that: Iterable[B]): LazyZip4[El1, El2, El3, B, C1] = new LazyZip4(src, coll1, coll2, coll3, that) + def lazyZip[B](that: Iterable[B]^): LazyZip4[El1, El2, El3, B, C1]^{this, that} = new LazyZip4(src, coll1, coll2, coll3, that) def map[B, C](f: (El1, El2, El3) => B)(implicit bf: BuildFrom[C1, B, C]): C = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -177,7 +178,7 @@ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, def flatMap[B, C](f: (El1, El2, El3) => Iterable[B])(implicit bf: BuildFrom[C1, B, C]): C = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -197,7 +198,7 @@ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, def filter[C](p: (El1, El2, El3) => Boolean)(implicit bf: BuildFrom[C1, (El1, El2, El3), C]): C = { bf.fromSpecific(src)(new AbstractView[(El1, El2, El3)] { - def iterator: AbstractIterator[(El1, El2, El3)] = new AbstractIterator[(El1, El2, El3)] { + def iterator = new AbstractIterator[(El1, El2, El3)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -249,7 +250,7 @@ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, } private def toIterable: View[(El1, El2, El3)] = new AbstractView[(El1, El2, El3)] { - def iterator: AbstractIterator[(El1, El2, El3)] = new AbstractIterator[(El1, El2, El3)] { + def iterator = new AbstractIterator[(El1, El2, El3)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -288,14 +289,14 @@ object LazyZip3 { * Note: will not terminate for infinite-sized collections. */ final class LazyZip4[+El1, +El2, +El3, +El4, C1] private[collection](src: C1, - coll1: Iterable[El1], - coll2: Iterable[El2], - coll3: Iterable[El3], - coll4: Iterable[El4]) { + coll1: Iterable[El1]^, + coll2: Iterable[El2]^, + coll3: Iterable[El3]^, + coll4: Iterable[El4]^) { def map[B, C](f: (El1, El2, El3, El4) => B)(implicit bf: BuildFrom[C1, B, C]): C = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -310,7 +311,7 @@ final class LazyZip4[+El1, +El2, +El3, +El4, C1] private[collection](src: C1, def flatMap[B, C](f: (El1, El2, El3, El4) => Iterable[B])(implicit bf: BuildFrom[C1, B, C]): C = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -331,7 +332,7 @@ final class LazyZip4[+El1, +El2, +El3, +El4, C1] private[collection](src: C1, def filter[C](p: (El1, El2, El3, El4) => Boolean)(implicit bf: BuildFrom[C1, (El1, El2, El3, El4), C]): C = { bf.fromSpecific(src)(new AbstractView[(El1, El2, El3, El4)] { - def iterator: AbstractIterator[(El1, El2, El3, El4)] = new AbstractIterator[(El1, El2, El3, El4)] { + def iterator = new AbstractIterator[(El1, El2, El3, El4)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -387,7 +388,7 @@ final class LazyZip4[+El1, +El2, +El3, +El4, C1] private[collection](src: C1, } private def toIterable: View[(El1, El2, El3, El4)] = new AbstractView[(El1, El2, El3, El4)] { - def iterator: AbstractIterator[(El1, El2, El3, El4)] = new AbstractIterator[(El1, El2, El3, El4)] { + def iterator = new AbstractIterator[(El1, El2, El3, El4)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator diff --git a/scala2-library-cc/src/scala/collection/LinearSeq.scala b/scala2-library-cc/src/scala/collection/LinearSeq.scala index 449d58c866e3..393f5fda4187 100644 --- a/scala2-library-cc/src/scala/collection/LinearSeq.scala +++ b/scala2-library-cc/src/scala/collection/LinearSeq.scala @@ -14,6 +14,7 @@ package scala package collection import scala.annotation.{nowarn, tailrec} +import language.experimental.captureChecking /** Base trait for linearly accessed sequences that have efficient `head` and * `tail` operations. @@ -32,7 +33,7 @@ trait LinearSeq[+A] extends Seq[A] object LinearSeq extends SeqFactory.Delegate[LinearSeq](immutable.LinearSeq) /** Base trait for linear Seq operations */ -trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeqOps[A, CC, C]] extends Any with SeqOps[A, CC, C] { +trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeqOps[A, CC, C]] extends AnyRef with SeqOps[A, CC, C] { /** @inheritdoc * @@ -96,7 +97,7 @@ trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeq else loop(0, coll) } - override def lengthCompare(that: Iterable[_]): Int = { + override def lengthCompare(that: Iterable[_]^): Int = { val thatKnownSize = that.knownSize if (thatKnownSize >= 0) this lengthCompare thatKnownSize @@ -186,7 +187,7 @@ trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeq acc } - override def sameElements[B >: A](that: IterableOnce[B]): Boolean = { + override def sameElements[B >: A](that: IterableOnce[B]^): Boolean = { @tailrec def linearSeqEq(a: LinearSeq[B], b: LinearSeq[B]): Boolean = (a eq b) || { if (a.nonEmpty && b.nonEmpty && a.head == b.head) { @@ -259,7 +260,7 @@ trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeq } } -trait StrictOptimizedLinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with StrictOptimizedLinearSeqOps[A, CC, C]] extends Any with LinearSeqOps[A, CC, C] with StrictOptimizedSeqOps[A, CC, C] { +trait StrictOptimizedLinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with StrictOptimizedLinearSeqOps[A, CC, C]] extends AnyRef with LinearSeqOps[A, CC, C] with StrictOptimizedSeqOps[A, CC, C] { // A more efficient iterator implementation than the default LinearSeqIterator override def iterator: Iterator[A] = new AbstractIterator[A] { private[this] var current = StrictOptimizedLinearSeqOps.this diff --git a/scala2-library-cc/src/scala/collection/Map.scala b/scala2-library-cc/src/scala/collection/Map.scala index 0fb6df9a06dc..8ab25a3c13e0 100644 --- a/scala2-library-cc/src/scala/collection/Map.scala +++ b/scala2-library-cc/src/scala/collection/Map.scala @@ -17,13 +17,16 @@ import scala.annotation.nowarn import scala.collection.generic.DefaultSerializable import scala.collection.mutable.StringBuilder import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure /** Base Map type */ trait Map[K, +V] extends Iterable[(K, V)] with MapOps[K, V, Map, Map[K, V]] with MapFactoryDefaults[K, V, Map, Iterable] - with Equals { + with Equals + with Pure { def mapFactory: scala.collection.MapFactory[Map] = Map @@ -101,8 +104,9 @@ trait Map[K, +V] trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] extends IterableOps[(K, V), Iterable, C] with PartialFunction[K, V] { + this: MapOps[K, V, CC, C]^ => - override def view: MapView[K, V] = new MapView.Id(this) + override def view: MapView[K, V]^{this} = new MapView.Id(this) /** Returns a [[Stepper]] for the keys of this map. See method [[stepper]]. */ def keyStepper[S <: Stepper[_]](implicit shape: StepperShape[K, S]): S = { @@ -131,7 +135,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] /** Similar to `fromIterable`, but returns a Map collection type. * Note that the return type is now `CC[K2, V2]`. */ - @`inline` protected final def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]): CC[K2, V2] = mapFactory.from(it) + @`inline` protected final def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]^): CC[K2, V2] = mapFactory.from(it) /** The companion object of this map, providing various factory methods. * @@ -251,7 +255,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * the predicate `p`. The resulting map wraps the original map without copying any elements. */ @deprecated("Use .view.filterKeys(f). A future version will include a strict version of this method (for now, .view.filterKeys(p).toMap).", "2.13.0") - def filterKeys(p: K => Boolean): MapView[K, V] = new MapView.FilterKeys(this, p) + def filterKeys(p: K => Boolean): MapView[K, V]^{this, p} = new MapView.FilterKeys(this, p) /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. @@ -259,7 +263,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ @deprecated("Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).", "2.13.0") - def mapValues[W](f: V => W): MapView[K, W] = new MapView.MapValues(this, f) + def mapValues[W](f: V => W): MapView[K, W]^{this, f} = new MapView.MapValues(this, f) /** Defines the default value computation for the map, * returned when a key is not found @@ -318,7 +322,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * @return a new $coll resulting from applying the given collection-valued function * `f` to each element of this $coll and concatenating the results. */ - def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = mapFactory.from(new View.FlatMap(this, f)) + def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): CC[K2, V2] = mapFactory.from(new View.FlatMap(this, f)) /** Returns a new $coll containing the elements from the left hand operand followed by the elements from the * right hand operand. The element type of the $coll is the most specific superclass encompassing @@ -328,7 +332,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * @return a new $coll which contains all elements * of this $coll followed by all elements of `suffix`. */ - def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]): CC[K, V2] = mapFactory.from(suffix match { + def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]^): CC[K, V2] = mapFactory.from(suffix match { case it: Iterable[(K, V2)] => new View.Concat(this, it) case _ => iterator.concat(suffix.iterator) }) @@ -336,7 +340,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] // Not final because subclasses refine the result type, e.g. in SortedMap, the result type is // SortedMap's CC, while Map's CC is fixed to Map /** Alias for `concat` */ - /*@`inline` final*/ def ++ [V2 >: V](xs: collection.IterableOnce[(K, V2)]): CC[K, V2] = concat(xs) + /*@`inline` final*/ def ++ [V2 >: V](xs: collection.IterableOnce[(K, V2)]^): CC[K, V2] = concat(xs) override def addString(sb: StringBuilder, start: String, sep: String, end: String): sb.type = iterator.map { case (k, v) => s"$k -> $v" }.addString(sb, start, sep, end) @@ -350,14 +354,14 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] mapFactory.from(new View.Concat(new View.Appended(new View.Appended(this, elem1), elem2), elems)) @deprecated("Consider requiring an immutable Map.", "2.13.0") - @`inline` def -- (keys: IterableOnce[K]): C = { + @`inline` def -- (keys: IterableOnce[K]^): C = { lazy val keysSet = keys.iterator.to(immutable.Set) - fromSpecific(this.view.filterKeys(k => !keysSet.contains(k))) + fromSpecific(this.view.filterKeys(k => !keysSet.contains(k))).unsafeAssumePure } @deprecated("Use ++ instead of ++: for collections of type Iterable", "2.13.0") - def ++: [V1 >: V](that: IterableOnce[(K,V1)]): CC[K,V1] = { - val thatIterable: Iterable[(K, V1)] = that match { + def ++: [V1 >: V](that: IterableOnce[(K,V1)]^): CC[K,V1] = { + val thatIterable: Iterable[(K, V1)]^{that} = that match { case that: Iterable[(K, V1)] => that case that => View.from(that) } @@ -373,17 +377,17 @@ object MapOps { */ @SerialVersionUID(3L) class WithFilter[K, +V, +IterableCC[_], +CC[_, _] <: IterableOps[_, AnyConstr, _]]( - self: MapOps[K, V, CC, _] with IterableOps[(K, V), IterableCC, _], + self: (MapOps[K, V, CC, _] with IterableOps[(K, V), IterableCC, _])^, p: ((K, V)) => Boolean ) extends IterableOps.WithFilter[(K, V), IterableCC](self, p) with Serializable { - def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = + def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2]^{this, f} = self.mapFactory.from(new View.Map(filtered, f)) - def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = + def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): CC[K2, V2]^{this, f} = self.mapFactory.from(new View.FlatMap(filtered, f)) - override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, CC] = + override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, CC]^{this, q} = new WithFilter[K, V, IterableCC, CC](self, (kv: (K, V)) => p(kv) && q(kv)) } diff --git a/scala2-library-cc/src/scala/collection/MapView.scala b/scala2-library-cc/src/scala/collection/MapView.scala index 7f84178a7c16..5909fe24fbbc 100644 --- a/scala2-library-cc/src/scala/collection/MapView.scala +++ b/scala2-library-cc/src/scala/collection/MapView.scala @@ -15,54 +15,57 @@ package scala.collection import scala.annotation.nowarn import scala.collection.MapView.SomeMapOps import scala.collection.mutable.Builder +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure trait MapView[K, +V] extends MapOps[K, V, ({ type l[X, Y] = View[(X, Y)] })#l, View[(K, V)]] with View[(K, V)] { + this: MapView[K, V]^ => - override def view: MapView[K, V] = this + override def view: MapView[K, V]^{this} = this // Ideally this returns a `View`, but bincompat /** Creates a view over all keys of this map. * * @return the keys of this map as a view. */ - override def keys: Iterable[K] = new MapView.Keys(this) + override def keys: Iterable[K]^{this} = new MapView.Keys(this) // Ideally this returns a `View`, but bincompat /** Creates a view over all values of this map. * * @return the values of this map as a view. */ - override def values: Iterable[V] = new MapView.Values(this) + override def values: Iterable[V]^{this} = new MapView.Values(this) /** Filters this map by retaining only keys satisfying a predicate. * @param p the predicate used to test keys * @return an immutable map consisting only of those key value pairs of this map where the key satisfies * the predicate `p`. The resulting map wraps the original map without copying any elements. */ - override def filterKeys(p: K => Boolean): MapView[K, V] = new MapView.FilterKeys(this, p) + override def filterKeys(p: K => Boolean): MapView[K, V]^{this, p} = new MapView.FilterKeys(this, p) /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. * @return a map view which maps every key of this map * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ - override def mapValues[W](f: V => W): MapView[K, W] = new MapView.MapValues(this, f) + override def mapValues[W](f: V => W): MapView[K, W]^{this, f} = new MapView.MapValues(this, f) - override def filter(pred: ((K, V)) => Boolean): MapView[K, V] = new MapView.Filter(this, false, pred) + override def filter(pred: ((K, V)) => Boolean): MapView[K, V]^{this, pred} = new MapView.Filter(this, false, pred) - override def filterNot(pred: ((K, V)) => Boolean): MapView[K, V] = new MapView.Filter(this, true, pred) + override def filterNot(pred: ((K, V)) => Boolean): MapView[K, V]^{this, pred} = new MapView.Filter(this, true, pred) - override def partition(p: ((K, V)) => Boolean): (MapView[K, V], MapView[K, V]) = (filter(p), filterNot(p)) + override def partition(p: ((K, V)) => Boolean): (MapView[K, V]^{this, p}, MapView[K, V]^{this, p}) = (filter(p), filterNot(p)) - override def tapEach[U](f: ((K, V)) => U): MapView[K, V] = new MapView.TapEach(this, f) + override def tapEach[U](f: ((K, V)) => U): MapView[K, V]^{this, f} = new MapView.TapEach(this, f) def mapFactory: MapViewFactory = MapView override def empty: MapView[K, V] = mapFactory.empty - override def withFilter(p: ((K, V)) => Boolean): MapOps.WithFilter[K, V, View, ({ type l[X, Y] = View[(X, Y)] })#l] = new MapOps.WithFilter(this, p) + override def withFilter(p: ((K, V)) => Boolean): MapOps.WithFilter[K, V, View, ({ type l[X, Y] = View[(X, Y)] })#l]^{this, p} = new MapOps.WithFilter(this, p) override def toString: String = super[View].toString @@ -78,7 +81,9 @@ object MapView extends MapViewFactory { type SomeMapOps[K, +V] = MapOps[K, V, SomeIterableConstr, _] @SerialVersionUID(3L) - private val EmptyMapView: MapView[Any, Nothing] = new AbstractMapView[Any, Nothing] { + object EmptyMapView extends AbstractMapView[Any, Nothing] { + // !!! cc problem: crash when we replace the line with + // private val EmptyMapView: MapView[Any, Nothing] = new AbstractMapView[Any, Nothing] { override def get(key: Any): Option[Nothing] = None override def iterator: Iterator[Nothing] = Iterator.empty[Nothing] override def knownSize: Int = 0 @@ -91,48 +96,48 @@ object MapView extends MapViewFactory { } @SerialVersionUID(3L) - class Id[K, +V](underlying: SomeMapOps[K, V]) extends AbstractMapView[K, V] { + class Id[K, +V](underlying: SomeMapOps[K, V]^) extends AbstractMapView[K, V] { def get(key: K): Option[V] = underlying.get(key) - def iterator: Iterator[(K, V)] = underlying.iterator + def iterator: Iterator[(K, V)]^{this} = underlying.iterator override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } // Ideally this is public, but bincompat @SerialVersionUID(3L) - private class Keys[K](underlying: SomeMapOps[K, _]) extends AbstractView[K] { - def iterator: Iterator[K] = underlying.keysIterator + private class Keys[K](underlying: SomeMapOps[K, _]^) extends AbstractView[K] { + def iterator: Iterator[K]^{this} = underlying.keysIterator override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } // Ideally this is public, but bincompat @SerialVersionUID(3L) - private class Values[+V](underlying: SomeMapOps[_, V]) extends AbstractView[V] { - def iterator: Iterator[V] = underlying.valuesIterator + private class Values[+V](underlying: SomeMapOps[_, V]^) extends AbstractView[V] { + def iterator: Iterator[V]^{this} = underlying.valuesIterator override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) - class MapValues[K, +V, +W](underlying: SomeMapOps[K, V], f: V => W) extends AbstractMapView[K, W] { - def iterator: Iterator[(K, W)] = underlying.iterator.map(kv => (kv._1, f(kv._2))) + class MapValues[K, +V, +W](underlying: SomeMapOps[K, V]^, f: V => W) extends AbstractMapView[K, W] { + def iterator: Iterator[(K, W)]^{this} = underlying.iterator.map(kv => (kv._1, f(kv._2))) def get(key: K): Option[W] = underlying.get(key).map(f) override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) - class FilterKeys[K, +V](underlying: SomeMapOps[K, V], p: K => Boolean) extends AbstractMapView[K, V] { - def iterator: Iterator[(K, V)] = underlying.iterator.filter { case (k, _) => p(k) } + class FilterKeys[K, +V](underlying: SomeMapOps[K, V]^, p: K => Boolean) extends AbstractMapView[K, V] { + def iterator: Iterator[(K, V)]^{this} = underlying.iterator.filter { case (k, _) => p(k) } def get(key: K): Option[V] = if (p(key)) underlying.get(key) else None override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) - class Filter[K, +V](underlying: SomeMapOps[K, V], isFlipped: Boolean, p: ((K, V)) => Boolean) extends AbstractMapView[K, V] { - def iterator: Iterator[(K, V)] = underlying.iterator.filterImpl(p, isFlipped) + class Filter[K, +V](underlying: SomeMapOps[K, V]^, isFlipped: Boolean, p: ((K, V)) => Boolean) extends AbstractMapView[K, V] { + def iterator: Iterator[(K, V)]^{this} = underlying.iterator.filterImpl(p, isFlipped) def get(key: K): Option[V] = underlying.get(key) match { case s @ Some(v) if p((key, v)) != isFlipped => s case _ => None @@ -142,7 +147,7 @@ object MapView extends MapViewFactory { } @SerialVersionUID(3L) - class TapEach[K, +V, +U](underlying: SomeMapOps[K, V], f: ((K, V)) => U) extends AbstractMapView[K, V] { + class TapEach[K, +V, +U](underlying: SomeMapOps[K, V]^, f: ((K, V)) => U) extends AbstractMapView[K, V] { override def get(key: K): Option[V] = { underlying.get(key) match { case s @ Some(v) => @@ -151,7 +156,7 @@ object MapView extends MapViewFactory { case None => None } } - override def iterator: Iterator[(K, V)] = underlying.iterator.tapEach(f) + override def iterator: Iterator[(K, V)]^{this} = underlying.iterator.tapEach(f) override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } @@ -160,9 +165,12 @@ object MapView extends MapViewFactory { override def empty[K, V]: MapView[K, V] = EmptyMapView.asInstanceOf[MapView[K, V]] - override def from[K, V](it: IterableOnce[(K, V)]): View[(K, V)] = View.from(it) + override def from[K, V](it: IterableOnce[(K, V)]^): View[(K, V)] = + View.from(it).unsafeAssumePure + // unsafeAssumePure needed here since MapViewFactory inherits from MapFactory, + // and the latter assumes maps are strict, so from's result captures nothing. - override def from[K, V](it: SomeMapOps[K, V]): MapView[K, V] = it match { + override def from[K, V](it: SomeMapOps[K, V]^): MapView[K, V]^{it} = it match { case mv: MapView[K, V] => mv case other => new MapView.Id(other) } @@ -176,12 +184,13 @@ trait MapViewFactory extends collection.MapFactory[({ type l[X, Y] = View[(X, Y) def empty[X, Y]: MapView[X, Y] - def from[K, V](it: SomeMapOps[K, V]): MapView[K, V] + def from[K, V](it: SomeMapOps[K, V]^): MapView[K, V]^{it} override def apply[K, V](elems: (K, V)*): MapView[K, V] = from(elems.toMap) } /** Explicit instantiation of the `MapView` trait to reduce class file size in subclasses. */ @SerialVersionUID(3L) -abstract class AbstractMapView[K, +V] extends AbstractView[(K, V)] with MapView[K, V] +abstract class AbstractMapView[K, +V] extends AbstractView[(K, V)] with MapView[K, V]: + this: AbstractMapView[K, V]^ => diff --git a/scala2-library-cc/src/scala/collection/Searching.scala b/scala2-library-cc/src/scala/collection/Searching.scala index 874a06449aa9..f5139422e24c 100644 --- a/scala2-library-cc/src/scala/collection/Searching.scala +++ b/scala2-library-cc/src/scala/collection/Searching.scala @@ -14,6 +14,7 @@ package scala.collection import scala.language.implicitConversions import scala.collection.generic.IsSeq +import language.experimental.captureChecking object Searching { diff --git a/scala2-library-cc/src/scala/collection/Seq.scala b/scala2-library-cc/src/scala/collection/Seq.scala index 514d855aa1cc..334546d67dad 100644 --- a/scala2-library-cc/src/scala/collection/Seq.scala +++ b/scala2-library-cc/src/scala/collection/Seq.scala @@ -16,6 +16,8 @@ import scala.collection.immutable.Range import scala.util.hashing.MurmurHash3 import Searching.{Found, InsertionPoint, SearchResult} import scala.annotation.nowarn +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure /** Base trait for sequence collections * @@ -27,6 +29,7 @@ trait Seq[+A] with SeqOps[A, Seq, Seq[A]] with IterableFactoryDefaults[A, Seq] with Equals { + this: Seq[A] => override def iterableFactory: SeqFactory[Seq] = Seq @@ -74,11 +77,12 @@ object Seq extends SeqFactory.Delegate[Seq](immutable.Seq) * @define coll sequence * @define Coll `Seq` */ -trait SeqOps[+A, +CC[_], +C] extends Any - with IterableOps[A, CC, C] { self => +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] @@ -160,13 +164,13 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @return a new $coll which contains all elements of `prefix` followed * by all the elements of this $coll. */ - def prependedAll[B >: A](prefix: IterableOnce[B]): CC[B] = iterableFactory.from(prefix match { + 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 }) /** Alias for `prependedAll` */ - @`inline` override final def ++: [B >: A](prefix: IterableOnce[B]): CC[B] = prependedAll(prefix) + @`inline` override final def ++: [B >: A](prefix: IterableOnce[B]^): CC[B] = prependedAll(prefix) /** Returns a new $coll containing the elements from the left hand operand followed by the elements from the * right hand operand. The element type of the $coll is the most specific superclass encompassing @@ -177,14 +181,15 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @return a new collection of type `CC[B]` which contains all elements * of this $coll followed by all elements of `suffix`. */ - def appendedAll[B >: A](suffix: IterableOnce[B]): CC[B] = super.concat(suffix) + def appendedAll[B >: A](suffix: IterableOnce[B]^): CC[B] = + super.concat(suffix).unsafeAssumePure /** Alias for `appendedAll` */ - @`inline` final def :++ [B >: A](suffix: IterableOnce[B]): CC[B] = appendedAll(suffix) + @`inline` final def :++ [B >: A](suffix: IterableOnce[B]^): CC[B] = appendedAll(suffix) // Make `concat` an alias for `appendedAll` so that it benefits from performance // overrides of this method - @`inline` final override def concat[B >: A](suffix: IterableOnce[B]): CC[B] = appendedAll(suffix) + @`inline` final override def concat[B >: A](suffix: IterableOnce[B]^): CC[B] = appendedAll(suffix) /** Produces a new sequence which contains all elements of this $coll and also all elements of * a given sequence. `xs union ys` is equivalent to `xs ++ ys`. @@ -212,7 +217,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @tparam B the type of the elements after being transformed by `f` * @return a new $coll consisting of all the elements of this $coll without duplicates. */ - def distinctBy[B](f: A => B): C = fromSpecific(new View.DistinctBy(this, f)) + def distinctBy[B](f: A -> B): C = fromSpecific(new View.DistinctBy(this, f)) /** Returns new $coll with elements in reversed order. * @@ -231,7 +236,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * * @return an iterator yielding the elements of this $coll in reversed order */ - def reverseIterator: Iterator[A] = reversed.iterator + override def reverseIterator: Iterator[A] = reversed.iterator /** Tests whether this $coll contains the given sequence at a given index. * @@ -243,7 +248,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @return `true` if the sequence `that` is contained in this $coll at * index `offset`, otherwise `false`. */ - def startsWith[B >: A](that: IterableOnce[B], offset: Int = 0): Boolean = { + def startsWith[B >: A](that: IterableOnce[B]^, offset: Int = 0): Boolean = { val i = iterator drop offset val j = that.iterator while (j.hasNext && i.hasNext) @@ -258,7 +263,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @param that the sequence to test * @return `true` if this $coll has `that` as a suffix, `false` otherwise. */ - def endsWith[B >: A](that: Iterable[B]): Boolean = { + def endsWith[B >: A](that: Iterable[B]^): Boolean = { if (that.isEmpty) true else { val i = iterator.drop(length - that.size) @@ -628,6 +633,9 @@ trait SeqOps[+A, +CC[_], +C] extends Any private[this] def init() = { val m = mutable.HashMap[A, Int]() + //val s1 = self.toGenericSeq map (e => (e, m.getOrElseUpdate(e, m.size))) + //val s2: Seq[(A, Int)] = s1 sortBy (_._2) + //val (es, is) = s2.unzip(using Predef.$conforms[(A, Int)]) val (es, is) = (self.toGenericSeq map (e => (e, m.getOrElseUpdate(e, m.size))) sortBy (_._2)).unzip (es.to(mutable.ArrayBuffer), is.toArray) @@ -723,8 +731,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any else if (len > 1) { b.sizeHint(len) val arr = new Array[Any](len) - @annotation.unused val copied = copyToArray(arr) - //assert(copied == len) + copyToArray(arr) java.util.Arrays.sort(arr.asInstanceOf[Array[AnyRef]], ord.asInstanceOf[Ordering[AnyRef]]) var i = 0 while (i < len) { @@ -808,7 +815,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any */ def lengthCompare(len: Int): Int = super.sizeCompare(len) - override final def sizeCompare(that: Iterable[_]): Int = lengthCompare(that) + override final def sizeCompare(that: Iterable[_]^): Int = lengthCompare(that) /** Compares the length of this $coll to the size of another `Iterable`. * @@ -823,7 +830,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * is `O(this.length min that.size)` instead of `O(this.length + that.size)`. * The method should be overridden if computing `size` is cheap and `knownSize` returns `-1`. */ - def lengthCompare(that: Iterable[_]): Int = super.sizeCompare(that) + def lengthCompare(that: Iterable[_]^): Int = super.sizeCompare(that) /** Returns a value class containing operations for comparing the length of this $coll to a test value. * @@ -846,7 +853,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any /** Are the elements of this collection the same (and in the same order) * as those of `that`? */ - def sameElements[B >: A](that: IterableOnce[B]): Boolean = { + def sameElements[B >: A](that: IterableOnce[B]^): Boolean = { val thisKnownSize = knownSize val knownSizeDifference = thisKnownSize != -1 && { val thatKnownSize = that.knownSize @@ -884,7 +891,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * part of the result, but any following occurrences will. */ def diff[B >: A](that: Seq[B]): C = { - val occ = occCounts(that) + val occ = occCounts[B](that) fromSpecific(iterator.filter { x => var include = false occ.updateWith(x) { @@ -909,7 +916,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * in the result, but any following occurrences will be omitted. */ def intersect[B >: A](that: Seq[B]): C = { - val occ = occCounts(that) + val occ = occCounts[B](that) fromSpecific(iterator.filter { x => var include = true occ.updateWith(x) { @@ -938,7 +945,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * except that `replaced` elements starting from `from` are replaced * by all the elements of `other`. */ - def patch[B >: A](from: Int, other: IterableOnce[B], replaced: Int): CC[B] = + def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] = iterableFactory.from(new View.Patched(this, from, other, replaced)) /** A copy of this $coll with one single replaced element. @@ -1005,11 +1012,11 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @return a `Found` value containing the index corresponding to the element in the * sequence, or the `InsertionPoint` where the element would be inserted if * the element is not in the sequence. - * + * * @note if `to <= from`, the search space is empty, and an `InsertionPoint` at `from` * is returned */ - def search[B >: A](elem: B, from: Int, to: Int) (implicit ord: Ordering[B]): SearchResult = + def search[B >: A](elem: B, from: Int, to: Int) (implicit ord: Ordering[B]): SearchResult = linearSearch(view.slice(from, to), elem, math.max(0, from))(ord) private[this] def linearSearch[B >: A](c: View[A], elem: B, offset: Int) diff --git a/scala2-library-cc/src/scala/collection/SeqMap.scala b/scala2-library-cc/src/scala/collection/SeqMap.scala index 05bf126aba02..a7f2c629b61d 100644 --- a/scala2-library-cc/src/scala/collection/SeqMap.scala +++ b/scala2-library-cc/src/scala/collection/SeqMap.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking import scala.annotation.nowarn diff --git a/scala2-library-cc/src/scala/collection/SeqView.scala b/scala2-library-cc/src/scala/collection/SeqView.scala index cddd39b9fddc..7ec22cd54c83 100644 --- a/scala2-library-cc/src/scala/collection/SeqView.scala +++ b/scala2-library-cc/src/scala/collection/SeqView.scala @@ -14,26 +14,49 @@ package scala package collection import scala.annotation.nowarn +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure +import scala.annotation.unchecked.uncheckedCaptures + +/** !!! Scala 2 difference: Need intermediate trait SeqViewOps to collect the + * necessary functionality over which SeqViews are defined, and at the same + * time allowing impure operations. Scala 2 uses SeqOps here, but SeqOps is + * pure, whereas SeqViews are Iterables which can be impure (for instance, + * mapping a SeqView with an impure function gives an impure view). + */ +trait SeqViewOps[+A, +CC[_], +C] extends Any with IterableOps[A, CC, C] { + self: SeqViewOps[A, CC, C]^ => + + def length: Int + def apply(x: Int): A + def appended[B >: A](elem: B): CC[B]^{this} + def prepended[B >: A](elem: B): CC[B]^{this} + def reverse: C^{this} + def sorted[B >: A](implicit ord: Ordering[B]): C^{this} + + def reverseIterator: Iterator[A]^{this} = reversed.iterator +} +trait SeqView[+A] extends SeqViewOps[A, View, View[A]] with View[A] { + self: SeqView[A]^ => -trait SeqView[+A] extends SeqOps[A, View, View[A]] with View[A] { - override def view: SeqView[A] = this + override def view: SeqView[A]^{this} = this - override def map[B](f: A => B): SeqView[B] = new SeqView.Map(this, f) - override def appended[B >: A](elem: B): SeqView[B] = new SeqView.Appended(this, elem) - override def prepended[B >: A](elem: B): SeqView[B] = new SeqView.Prepended(elem, this) - override def reverse: SeqView[A] = new SeqView.Reverse(this) - override def take(n: Int): SeqView[A] = new SeqView.Take(this, n) - override def drop(n: Int): SeqView[A] = new SeqView.Drop(this, n) - override def takeRight(n: Int): SeqView[A] = new SeqView.TakeRight(this, n) - override def dropRight(n: Int): SeqView[A] = new SeqView.DropRight(this, n) - override def tapEach[U](f: A => U): SeqView[A] = new SeqView.Map(this, { (a: A) => f(a); a }) + override def map[B](f: A => B): SeqView[B]^{this, f} = new SeqView.Map(this, f) + override def appended[B >: A](elem: B): SeqView[B]^{this} = new SeqView.Appended(this, elem) + override def prepended[B >: A](elem: B): SeqView[B]^{this} = new SeqView.Prepended(elem, this) + override def reverse: SeqView[A]^{this} = new SeqView.Reverse(this) + override def take(n: Int): SeqView[A]^{this} = new SeqView.Take(this, n) + override def drop(n: Int): SeqView[A]^{this} = new SeqView.Drop(this, n) + override def takeRight(n: Int): SeqView[A]^{this} = new SeqView.TakeRight(this, n) + override def dropRight(n: Int): SeqView[A]^{this} = new SeqView.DropRight(this, n) + override def tapEach[U](f: A => U): SeqView[A]^{this, f} = new SeqView.Map(this, { (a: A) => f(a); a }) - def concat[B >: A](suffix: SeqView.SomeSeqOps[B]): SeqView[B] = new SeqView.Concat(this, suffix) - def appendedAll[B >: A](suffix: SeqView.SomeSeqOps[B]): SeqView[B] = new SeqView.Concat(this, suffix) - def prependedAll[B >: A](prefix: SeqView.SomeSeqOps[B]): SeqView[B] = new SeqView.Concat(prefix, this) + def concat[B >: A](suffix: SeqView.SomeSeqOps[B]): SeqView[B]^{this} = new SeqView.Concat(this, suffix) + def appendedAll[B >: A](suffix: SeqView.SomeSeqOps[B]): SeqView[B]^{this} = new SeqView.Concat(this, suffix) + def prependedAll[B >: A](prefix: SeqView.SomeSeqOps[B]): SeqView[B]^{this} = new SeqView.Concat(prefix, this) - override def sorted[B >: A](implicit ord: Ordering[B]): SeqView[A] = new SeqView.Sorted(this, ord) + override def sorted[B >: A](implicit ord: Ordering[B]): SeqView[A]^{this} = new SeqView.Sorted(this, ord) @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix: String = "SeqView" @@ -42,38 +65,38 @@ trait SeqView[+A] extends SeqOps[A, View, View[A]] with View[A] { object SeqView { /** A `SeqOps` whose collection type and collection type constructor are unknown */ - private type SomeSeqOps[+A] = SeqOps[A, AnyConstr, _] + private type SomeSeqOps[+A] = SeqViewOps[A, AnyConstr, _] /** A view that doesn’t apply any transformation to an underlying sequence */ @SerialVersionUID(3L) - class Id[+A](underlying: SomeSeqOps[A]) extends AbstractSeqView[A] { + class Id[+A](underlying: SomeSeqOps[A]^) extends AbstractSeqView[A] { def apply(idx: Int): A = underlying.apply(idx) def length: Int = underlying.length - def iterator: Iterator[A] = underlying.iterator + def iterator: Iterator[A]^{this} = underlying.iterator override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) - class Map[+A, +B](underlying: SomeSeqOps[A], f: A => B) extends View.Map[A, B](underlying, f) with SeqView[B] { + class Map[+A, +B](underlying: SomeSeqOps[A]^, f: A => B) extends View.Map[A, B](underlying, f) with SeqView[B] { def apply(idx: Int): B = f(underlying(idx)) def length: Int = underlying.length } @SerialVersionUID(3L) - class Appended[+A](underlying: SomeSeqOps[A], elem: A) extends View.Appended(underlying, elem) with SeqView[A] { + class Appended[+A](underlying: SomeSeqOps[A]^, elem: A) extends View.Appended(underlying, elem) with SeqView[A] { def apply(idx: Int): A = if (idx == underlying.length) elem else underlying(idx) def length: Int = underlying.length + 1 } @SerialVersionUID(3L) - class Prepended[+A](elem: A, underlying: SomeSeqOps[A]) extends View.Prepended(elem, underlying) with SeqView[A] { + class Prepended[+A](elem: A, underlying: SomeSeqOps[A]^) extends View.Prepended(elem, underlying) with SeqView[A] { def apply(idx: Int): A = if (idx == 0) elem else underlying(idx - 1) def length: Int = underlying.length + 1 } @SerialVersionUID(3L) - class Concat[A](prefix: SomeSeqOps[A], suffix: SomeSeqOps[A]) extends View.Concat[A](prefix, suffix) with SeqView[A] { + class Concat[A](prefix: SomeSeqOps[A]^, suffix: SomeSeqOps[A]^) extends View.Concat[A](prefix, suffix) with SeqView[A] { def apply(idx: Int): A = { val l = prefix.length if (idx < l) prefix(idx) else suffix(idx - l) @@ -82,16 +105,16 @@ object SeqView { } @SerialVersionUID(3L) - class Reverse[A](underlying: SomeSeqOps[A]) extends AbstractSeqView[A] { + class Reverse[A](underlying: SomeSeqOps[A]^) extends AbstractSeqView[A] { def apply(i: Int) = underlying.apply(size - 1 - i) def length = underlying.size - def iterator: Iterator[A] = underlying.reverseIterator + def iterator: Iterator[A]^{this} = underlying.reverseIterator override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) - class Take[+A](underlying: SomeSeqOps[A], n: Int) extends View.Take(underlying, n) with SeqView[A] { + class Take[+A](underlying: SomeSeqOps[A]^, n: Int) extends View.Take(underlying, n) with SeqView[A] { def apply(idx: Int): A = if (idx < n) { underlying(idx) } else { @@ -101,7 +124,7 @@ object SeqView { } @SerialVersionUID(3L) - class TakeRight[+A](underlying: SomeSeqOps[A], n: Int) extends View.TakeRight(underlying, n) with SeqView[A] { + class TakeRight[+A](underlying: SomeSeqOps[A]^, n: Int) extends View.TakeRight(underlying, n) with SeqView[A] { private[this] val delta = (underlying.size - (n max 0)) max 0 def length = underlying.size - delta @throws[IndexOutOfBoundsException] @@ -109,15 +132,15 @@ object SeqView { } @SerialVersionUID(3L) - class Drop[A](underlying: SomeSeqOps[A], n: Int) extends View.Drop[A](underlying, n) with SeqView[A] { + class Drop[A](underlying: SomeSeqOps[A]^, n: Int) extends View.Drop[A](underlying, n) with SeqView[A] { def length = (underlying.size - normN) max 0 @throws[IndexOutOfBoundsException] def apply(i: Int) = underlying.apply(i + normN) - override def drop(n: Int): SeqView[A] = new Drop(underlying, this.n + n) + override def drop(n: Int): SeqView[A]^{this} = new Drop(underlying, this.n + n) } @SerialVersionUID(3L) - class DropRight[A](underlying: SomeSeqOps[A], n: Int) extends View.DropRight[A](underlying, n) with SeqView[A] { + class DropRight[A](underlying: SomeSeqOps[A]^, n: Int) extends View.DropRight[A](underlying, n) with SeqView[A] { private[this] val len = (underlying.size - (n max 0)) max 0 def length = len @throws[IndexOutOfBoundsException] @@ -125,15 +148,15 @@ object SeqView { } @SerialVersionUID(3L) - class Sorted[A, B >: A] private (private[this] var underlying: SomeSeqOps[A], + class Sorted[A, B >: A] private (private[this] var underlying: SomeSeqOps[A]^, private[this] val len: Int, ord: Ordering[B]) extends SeqView[A] { - outer => + outer: Sorted[A, B]^ => // force evaluation immediately by calling `length` so infinite collections // hang on `sorted`/`sortWith`/`sortBy` rather than on arbitrary method calls - def this(underlying: SomeSeqOps[A], ord: Ordering[B]) = this(underlying, underlying.length, ord) + def this(underlying: SomeSeqOps[A]^, ord: Ordering[B]) = this(underlying, underlying.length, ord) @SerialVersionUID(3L) private[this] class ReverseSorted extends SeqView[A] { @@ -141,15 +164,15 @@ object SeqView { def apply(i: Int): A = _reversed.apply(i) def length: Int = len - def iterator: Iterator[A] = Iterator.empty ++ _reversed.iterator // very lazy + def iterator: Iterator[A]^{this} = Iterator.empty ++ _reversed.iterator // very lazy override def knownSize: Int = len override def isEmpty: Boolean = len == 0 override def to[C1](factory: Factory[A, C1]): C1 = _reversed.to(factory) - override def reverse: SeqView[A] = outer - override protected def reversed: Iterable[A] = outer + override def reverse: SeqView[A]^{outer} = outer + override protected def reversed: Iterable[A] = outer.unsafeAssumePure - override def sorted[B1 >: A](implicit ord1: Ordering[B1]): SeqView[A] = - if (ord1 == Sorted.this.ord) outer + override def sorted[B1 >: A](implicit ord1: Ordering[B1]): SeqView[A]^{this} = + if (ord1 == Sorted.this.ord) outer.unsafeAssumePure else if (ord1.isReverseOf(Sorted.this.ord)) this else new Sorted(elems, len, ord1) } @@ -163,8 +186,7 @@ object SeqView { else if (len == 1) List(underlying.head) else { val arr = new Array[Any](len) // Array[Any] =:= Array[AnyRef] - @annotation.unused val copied = underlying.copyToArray(arr) - //assert(copied == len) + underlying.copyToArray(arr) java.util.Arrays.sort(arr.asInstanceOf[Array[AnyRef]], ord.asInstanceOf[Ordering[AnyRef]]) // casting the Array[AnyRef] to Array[A] and creating an ArraySeq from it // is safe because: @@ -182,14 +204,14 @@ object SeqView { res } - private[this] def elems: SomeSeqOps[A] = { + private[this] def elems: SomeSeqOps[A]^{this} = { val orig = underlying if (evaluated) _sorted else orig } def apply(i: Int): A = _sorted.apply(i) def length: Int = len - def iterator: Iterator[A] = Iterator.empty ++ _sorted.iterator // very lazy + def iterator: Iterator[A]^{this} = Iterator.empty ++ _sorted.iterator // very lazy override def knownSize: Int = len override def isEmpty: Boolean = len == 0 override def to[C1](factory: Factory[A, C1]): C1 = _sorted.to(factory) @@ -198,7 +220,7 @@ object SeqView { // so this is acceptable for `reversed` override protected def reversed: Iterable[A] = new ReverseSorted - override def sorted[B1 >: A](implicit ord1: Ordering[B1]): SeqView[A] = + override def sorted[B1 >: A](implicit ord1: Ordering[B1]): SeqView[A]^{this} = if (ord1 == this.ord) this else if (ord1.isReverseOf(this.ord)) reverse else new Sorted(elems, len, ord1) diff --git a/scala2-library-cc/src/scala/collection/Set.scala b/scala2-library-cc/src/scala/collection/Set.scala index 0ea1e5689473..a9c279b82a49 100644 --- a/scala2-library-cc/src/scala/collection/Set.scala +++ b/scala2-library-cc/src/scala/collection/Set.scala @@ -17,6 +17,7 @@ import scala.util.hashing.MurmurHash3 import java.lang.String import scala.annotation.nowarn +import language.experimental.captureChecking /** Base trait for set collections. */ @@ -24,7 +25,9 @@ trait Set[A] extends Iterable[A] with SetOps[A, Set, Set[A]] with Equals - with IterableFactoryDefaults[A, Set] { + with IterableFactoryDefaults[A, Set] + with Pure { + self: Set[A] => def canEqual(that: Any) = true @@ -86,8 +89,7 @@ trait Set[A] * @define Coll `Set` */ trait SetOps[A, +CC[_], +C <: SetOps[A, CC, C]] - extends IterableOps[A, CC, C] - with (A => Boolean) { + extends IterableOps[A, CC, C], (A -> Boolean) { self => def contains(elem: A): Boolean @@ -234,7 +236,7 @@ trait SetOps[A, +CC[_], +C <: SetOps[A, CC, C]] case that: collection.Iterable[A] => new View.Concat(this, that) case _ => iterator.concat(that.iterator) }) - } + } @deprecated("Consider requiring an immutable Set or fall back to Set.union", "2.13.0") def + (elem: A): C = fromSpecific(new View.Appended(this, elem)) diff --git a/scala2-library-cc/src/scala/collection/SortedMap.scala b/scala2-library-cc/src/scala/collection/SortedMap.scala index 03ab0bb0dadc..7b9381ebb078 100644 --- a/scala2-library-cc/src/scala/collection/SortedMap.scala +++ b/scala2-library-cc/src/scala/collection/SortedMap.scala @@ -14,6 +14,7 @@ package scala package collection import scala.annotation.{implicitNotFound, nowarn} +import language.experimental.captureChecking /** A Map whose keys are sorted according to a [[scala.math.Ordering]]*/ trait SortedMap[K, +V] @@ -49,7 +50,8 @@ trait SortedMap[K, +V] trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], +C <: SortedMapOps[K, V, CC, C]] extends MapOps[K, V, Map, C] - with SortedOps[K, C] { + with SortedOps[K, C] + with Pure { /** The companion object of this sorted map, providing various factory methods. * @@ -176,13 +178,13 @@ trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = sortedMapFactory.from(new View.Collect(this, pf)) - override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]): CC[K, V2] = sortedMapFactory.from(suffix match { + override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]^): CC[K, V2] = sortedMapFactory.from(suffix match { case it: Iterable[(K, V2)] => new View.Concat(this, it) case _ => iterator.concat(suffix.iterator) })(ordering) /** Alias for `concat` */ - @`inline` override final def ++ [V2 >: V](xs: IterableOnce[(K, V2)]): CC[K, V2] = concat(xs) + @`inline` override final def ++ [V2 >: V](xs: IterableOnce[(K, V2)]^): CC[K, V2] = concat(xs) @deprecated("Consider requiring an immutable Map or fall back to Map.concat", "2.13.0") override def + [V1 >: V](kv: (K, V1)): CC[K, V1] = sortedMapFactory.from(new View.Appended(this, kv))(ordering) @@ -206,10 +208,10 @@ object SortedMapOps { def map[K2 : Ordering, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = self.sortedMapFactory.from(new View.Map(filtered, f)) - def flatMap[K2 : Ordering, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = + def flatMap[K2 : Ordering, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): CC[K2, V2] = self.sortedMapFactory.from(new View.FlatMap(filtered, f)) - override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, MapCC, CC] = + override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, MapCC, CC]^{this, q} = new WithFilter[K, V, IterableCC, MapCC, CC](self, (kv: (K, V)) => p(kv) && q(kv)) } diff --git a/scala2-library-cc/src/scala/collection/SortedOps.scala b/scala2-library-cc/src/scala/collection/SortedOps.scala index 64e6376be042..16751d86d9d5 100644 --- a/scala2-library-cc/src/scala/collection/SortedOps.scala +++ b/scala2-library-cc/src/scala/collection/SortedOps.scala @@ -12,6 +12,7 @@ package scala.collection +import language.experimental.captureChecking /** Base trait for sorted collections */ trait SortedOps[A, +C] { diff --git a/scala2-library-cc/src/scala/collection/SortedSet.scala b/scala2-library-cc/src/scala/collection/SortedSet.scala index c98ca9ae5523..639dc9ddead0 100644 --- a/scala2-library-cc/src/scala/collection/SortedSet.scala +++ b/scala2-library-cc/src/scala/collection/SortedSet.scala @@ -14,6 +14,7 @@ package scala.collection import scala.annotation.{implicitNotFound, nowarn} import scala.annotation.unchecked.uncheckedVariance +import language.experimental.captureChecking /** Base type of sorted sets */ trait SortedSet[A] extends Set[A] @@ -68,7 +69,6 @@ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] * @param start The lower-bound (inclusive) of the iterator */ def iteratorFrom(start: A): Iterator[A] - @deprecated("Use `iteratorFrom` instead.", "2.13.0") @`inline` def keysIteratorFrom(start: A): Iterator[A] = iteratorFrom(start) @@ -178,7 +178,7 @@ object SortedSetOps { def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = self.sortedIterableFactory.from(new View.FlatMap(filtered, f)) - override def withFilter(q: A => Boolean): WithFilter[A, IterableCC, CC] = + override def withFilter(q: A => Boolean): WithFilter[A, IterableCC, CC]^{this, q} = new WithFilter[A, IterableCC, CC](self, (a: A) => p(a) && q(a)) } diff --git a/scala2-library-cc/src/scala/collection/Stepper.scala b/scala2-library-cc/src/scala/collection/Stepper.scala index 0eeb8a44cb72..0a0ac0075990 100644 --- a/scala2-library-cc/src/scala/collection/Stepper.scala +++ b/scala2-library-cc/src/scala/collection/Stepper.scala @@ -15,6 +15,7 @@ package scala.collection import java.util.function.{Consumer, DoubleConsumer, IntConsumer, LongConsumer} import java.util.{PrimitiveIterator, Spliterator, Iterator => JIterator} import java.{lang => jl} +import language.experimental.captureChecking import scala.collection.Stepper.EfficientSplit @@ -38,6 +39,8 @@ import scala.collection.Stepper.EfficientSplit * @tparam A the element type of the Stepper */ trait Stepper[@specialized(Double, Int, Long) +A] { + this: Stepper[A]^ => + /** Check if there's an element available. */ def hasStep: Boolean @@ -183,9 +186,11 @@ object Stepper { /** A Stepper for arbitrary element types. See [[Stepper]]. */ trait AnyStepper[+A] extends Stepper[A] { + this: AnyStepper[A]^ => + def trySplit(): AnyStepper[A] - def spliterator[B >: A]: Spliterator[B] = new AnyStepper.AnyStepperSpliterator(this) + def spliterator[B >: A]: Spliterator[B]^{this} = new AnyStepper.AnyStepperSpliterator(this) def javaIterator[B >: A]: JIterator[B] = new JIterator[B] { def hasNext: Boolean = hasStep @@ -194,10 +199,10 @@ trait AnyStepper[+A] extends Stepper[A] { } object AnyStepper { - class AnyStepperSpliterator[A](s: AnyStepper[A]) extends Spliterator[A] { + class AnyStepperSpliterator[A](s: AnyStepper[A]^) extends Spliterator[A] { def tryAdvance(c: Consumer[_ >: A]): Boolean = if (s.hasStep) { c.accept(s.nextStep()); true } else false - def trySplit(): Spliterator[A] = { + def trySplit(): Spliterator[A]^{this} = { val sp = s.trySplit() if (sp == null) null else sp.spliterator } @@ -253,9 +258,11 @@ object AnyStepper { /** A Stepper for Ints. See [[Stepper]]. */ trait IntStepper extends Stepper[Int] { + this: IntStepper^ => + def trySplit(): IntStepper - def spliterator[B >: Int]: Spliterator.OfInt = new IntStepper.IntStepperSpliterator(this) + def spliterator[B >: Int]: Spliterator.OfInt^{this} = new IntStepper.IntStepperSpliterator(this) def javaIterator[B >: Int]: PrimitiveIterator.OfInt = new PrimitiveIterator.OfInt { def hasNext: Boolean = hasStep @@ -263,7 +270,7 @@ trait IntStepper extends Stepper[Int] { } } object IntStepper { - class IntStepperSpliterator(s: IntStepper) extends Spliterator.OfInt { + class IntStepperSpliterator(s: IntStepper^) extends Spliterator.OfInt { def tryAdvance(c: IntConsumer): Boolean = if (s.hasStep) { c.accept(s.nextStep()); true } else false // Override for efficiency: don't wrap the function and call the `tryAdvance` overload @@ -272,7 +279,7 @@ object IntStepper { case _ => if (s.hasStep) { c.accept(jl.Integer.valueOf(s.nextStep())); true } else false } // override required for dotty#6152 - override def trySplit(): Spliterator.OfInt = { + override def trySplit(): Spliterator.OfInt^{this} = { val sp = s.trySplit() if (sp == null) null else sp.spliterator } @@ -291,18 +298,19 @@ object IntStepper { /** A Stepper for Doubles. See [[Stepper]]. */ trait DoubleStepper extends Stepper[Double] { + this: DoubleStepper^ => def trySplit(): DoubleStepper - def spliterator[B >: Double]: Spliterator.OfDouble = new DoubleStepper.DoubleStepperSpliterator(this) + def spliterator[B >: Double]: Spliterator.OfDouble^{this} = new DoubleStepper.DoubleStepperSpliterator(this) - def javaIterator[B >: Double]: PrimitiveIterator.OfDouble = new PrimitiveIterator.OfDouble { + def javaIterator[B >: Double]: PrimitiveIterator.OfDouble^{this} = new PrimitiveIterator.OfDouble { def hasNext: Boolean = hasStep def nextDouble(): Double = nextStep() } } object DoubleStepper { - class DoubleStepperSpliterator(s: DoubleStepper) extends Spliterator.OfDouble { + class DoubleStepperSpliterator(s: DoubleStepper^) extends Spliterator.OfDouble { def tryAdvance(c: DoubleConsumer): Boolean = if (s.hasStep) { c.accept(s.nextStep()); true } else false // Override for efficiency: don't wrap the function and call the `tryAdvance` overload @@ -311,7 +319,7 @@ object DoubleStepper { case _ => if (s.hasStep) { c.accept(java.lang.Double.valueOf(s.nextStep())); true } else false } // override required for dotty#6152 - override def trySplit(): Spliterator.OfDouble = { + override def trySplit(): Spliterator.OfDouble^{this} = { val sp = s.trySplit() if (sp == null) null else sp.spliterator } @@ -330,18 +338,20 @@ object DoubleStepper { /** A Stepper for Longs. See [[Stepper]]. */ trait LongStepper extends Stepper[Long] { - def trySplit(): LongStepper + this: LongStepper^ => + + def trySplit(): LongStepper^{this} - def spliterator[B >: Long]: Spliterator.OfLong = new LongStepper.LongStepperSpliterator(this) + def spliterator[B >: Long]: Spliterator.OfLong^{this} = new LongStepper.LongStepperSpliterator(this) - def javaIterator[B >: Long]: PrimitiveIterator.OfLong = new PrimitiveIterator.OfLong { + def javaIterator[B >: Long]: PrimitiveIterator.OfLong^{this} = new PrimitiveIterator.OfLong { def hasNext: Boolean = hasStep def nextLong(): Long = nextStep() } } object LongStepper { - class LongStepperSpliterator(s: LongStepper) extends Spliterator.OfLong { + class LongStepperSpliterator(s: LongStepper^) extends Spliterator.OfLong { def tryAdvance(c: LongConsumer): Boolean = if (s.hasStep) { c.accept(s.nextStep()); true } else false // Override for efficiency: don't wrap the function and call the `tryAdvance` overload @@ -350,7 +360,7 @@ object LongStepper { case _ => if (s.hasStep) { c.accept(java.lang.Long.valueOf(s.nextStep())); true } else false } // override required for dotty#6152 - override def trySplit(): Spliterator.OfLong = { + override def trySplit(): Spliterator.OfLong^{this} = { val sp = s.trySplit() if (sp == null) null else sp.spliterator } diff --git a/scala2-library-cc/src/scala/collection/StepperShape.scala b/scala2-library-cc/src/scala/collection/StepperShape.scala index 6712073b09e4..c6b520400d89 100644 --- a/scala2-library-cc/src/scala/collection/StepperShape.scala +++ b/scala2-library-cc/src/scala/collection/StepperShape.scala @@ -14,12 +14,13 @@ package scala.collection import java.{lang => jl} +import language.experimental.captureChecking import scala.collection.Stepper.EfficientSplit /** An implicit StepperShape instance is used in the [[IterableOnce.stepper]] to return a possibly * specialized Stepper `S` according to the element type `T`. */ -sealed trait StepperShape[-T, S <: Stepper[_]] { +sealed trait StepperShape[-T, S <: Stepper[_]^] extends Pure { /** Return the Int constant (as defined in the `StepperShape` companion object) for this `StepperShape`. */ def shape: StepperShape.Shape diff --git a/scala2-library-cc/src/scala/collection/StrictOptimizedIterableOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedIterableOps.scala index a09766cfa912..5b504a2469b5 100644 --- a/scala2-library-cc/src/scala/collection/StrictOptimizedIterableOps.scala +++ b/scala2-library-cc/src/scala/collection/StrictOptimizedIterableOps.scala @@ -16,6 +16,7 @@ package collection import scala.annotation.nowarn import scala.annotation.unchecked.uncheckedVariance import scala.runtime.Statics +import language.experimental.captureChecking /** * Trait that overrides iterable operations to take advantage of strict builders. @@ -27,6 +28,7 @@ import scala.runtime.Statics trait StrictOptimizedIterableOps[+A, +CC[_], +C] extends Any with IterableOps[A, CC, C] { + this: StrictOptimizedIterableOps[A, CC, C] => // Optimized, push-based version of `partition` override def partition(p: A => Boolean): (C, C) = { @@ -55,7 +57,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] (first.result(), second.result()) } - override def unzip[A1, A2](implicit asPair: A => (A1, A2)): (CC[A1], CC[A2]) = { + override def unzip[A1, A2](implicit asPair: A -> (A1, A2)): (CC[A1], CC[A2]) = { val first = iterableFactory.newBuilder[A1] val second = iterableFactory.newBuilder[A2] foreach { a => @@ -66,7 +68,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] (first.result(), second.result()) } - override def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)): (CC[A1], CC[A2], CC[A3]) = { + override def unzip3[A1, A2, A3](implicit asTriple: A -> (A1, A2, A3)): (CC[A1], CC[A2], CC[A3]) = { val b1 = iterableFactory.newBuilder[A1] val b2 = iterableFactory.newBuilder[A2] val b3 = iterableFactory.newBuilder[A3] @@ -102,7 +104,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] b.result() } - override def flatMap[B](f: A => IterableOnce[B]): CC[B] = + override def flatMap[B](f: A => IterableOnce[B]^): CC[B] = strictOptimizedFlatMap(iterableFactory.newBuilder, f) /** @@ -112,7 +114,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] * @tparam C2 Type of the resulting collection (e.g. `List[String]`) * @return The resulting collection */ - @inline protected[this] final def strictOptimizedFlatMap[B, C2](b: mutable.Builder[B, C2], f: A => IterableOnce[B]): C2 = { + @inline protected[this] final def strictOptimizedFlatMap[B, C2](b: mutable.Builder[B, C2], f: A => IterableOnce[B]^): C2 = { val it = iterator while (it.hasNext) { b ++= f(it.next()) @@ -127,13 +129,13 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] * @tparam C2 Type of the resulting collection (e.g. `List[Int]`) * @return The resulting collection */ - @inline protected[this] final def strictOptimizedConcat[B >: A, C2](that: IterableOnce[B], b: mutable.Builder[B, C2]): C2 = { + @inline protected[this] final def strictOptimizedConcat[B >: A, C2](that: IterableOnce[B]^, b: mutable.Builder[B, C2]): C2 = { b ++= this b ++= that b.result() } - override def collect[B](pf: PartialFunction[A, B]): CC[B] = + override def collect[B](pf: PartialFunction[A, B]^): CC[B] = strictOptimizedCollect(iterableFactory.newBuilder, pf) /** @@ -143,7 +145,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] * @tparam C2 Type of the resulting collection (e.g. `List[String]`) * @return The resulting collection */ - @inline protected[this] final def strictOptimizedCollect[B, C2](b: mutable.Builder[B, C2], pf: PartialFunction[A, B]): C2 = { + @inline protected[this] final def strictOptimizedCollect[B, C2](b: mutable.Builder[B, C2], pf: PartialFunction[A, B]^): C2 = { val marker = Statics.pfMarker val it = iterator while (it.hasNext) { @@ -154,7 +156,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] b.result() } - override def flatten[B](implicit toIterableOnce: A => IterableOnce[B]): CC[B] = + override def flatten[B](implicit toIterableOnce: A -> IterableOnce[B]): CC[B] = strictOptimizedFlatten(iterableFactory.newBuilder) /** @@ -164,7 +166,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] * @tparam C2 Type of the resulting collection (e.g. `List[Int]`) * @return The resulting collection */ - @inline protected[this] final def strictOptimizedFlatten[B, C2](b: mutable.Builder[B, C2])(implicit toIterableOnce: A => IterableOnce[B]): C2 = { + @inline protected[this] final def strictOptimizedFlatten[B, C2](b: mutable.Builder[B, C2])(implicit toIterableOnce: A -> IterableOnce[B]): C2 = { val it = iterator while (it.hasNext) { b ++= toIterableOnce(it.next()) @@ -172,7 +174,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] b.result() } - override def zip[B](that: IterableOnce[B]): CC[(A @uncheckedVariance, B)] = + override def zip[B](that: IterableOnce[B]^): CC[(A @uncheckedVariance, B)] = strictOptimizedZip(that, iterableFactory.newBuilder[(A, B)]) /** @@ -182,7 +184,7 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] * @tparam C2 Type of the resulting collection (e.g. `List[(Int, String)]`) * @return The resulting collection */ - @inline protected[this] final def strictOptimizedZip[B, C2](that: IterableOnce[B], b: mutable.Builder[(A, B), C2]): C2 = { + @inline protected[this] final def strictOptimizedZip[B, C2](that: IterableOnce[B]^, b: mutable.Builder[(A, B), C2]): C2 = { val it1 = iterator val it2 = that.iterator while (it1.hasNext && it2.hasNext) { diff --git a/scala2-library-cc/src/scala/collection/StrictOptimizedMapOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedMapOps.scala index 1f5791bbb718..a9c5e0af43b3 100644 --- a/scala2-library-cc/src/scala/collection/StrictOptimizedMapOps.scala +++ b/scala2-library-cc/src/scala/collection/StrictOptimizedMapOps.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking /** * Trait that overrides map operations to take advantage of strict builders. @@ -22,15 +23,16 @@ package scala.collection */ trait StrictOptimizedMapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] extends MapOps[K, V, CC, C] - with StrictOptimizedIterableOps[(K, V), Iterable, C] { + with StrictOptimizedIterableOps[(K, V), Iterable, C] + with Pure { override def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = strictOptimizedMap(mapFactory.newBuilder, f) - override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = + override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): CC[K2, V2] = strictOptimizedFlatMap(mapFactory.newBuilder, f) - override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]): CC[K, V2] = + override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]^): CC[K, V2] = strictOptimizedConcat(suffix, mapFactory.newBuilder) override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]): CC[K2, V2] = diff --git a/scala2-library-cc/src/scala/collection/StrictOptimizedSeqOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSeqOps.scala index 396e53885081..b8af7e5f172b 100644 --- a/scala2-library-cc/src/scala/collection/StrictOptimizedSeqOps.scala +++ b/scala2-library-cc/src/scala/collection/StrictOptimizedSeqOps.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking /** * Trait that overrides operations on sequences in order @@ -21,7 +22,7 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] with SeqOps[A, CC, C] with StrictOptimizedIterableOps[A, CC, C] { - override def distinctBy[B](f: A => B): C = { + override def distinctBy[B](f: A -> B): C = { val builder = newSpecificBuilder val seen = mutable.HashSet.empty[B] val it = this.iterator @@ -52,10 +53,10 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] b.result() } - override def appendedAll[B >: A](suffix: IterableOnce[B]): CC[B] = + override def appendedAll[B >: A](suffix: IterableOnce[B]^): CC[B] = strictOptimizedConcat(suffix, iterableFactory.newBuilder) - override def prependedAll[B >: A](prefix: IterableOnce[B]): CC[B] = { + override def prependedAll[B >: A](prefix: IterableOnce[B]^): CC[B] = { val b = iterableFactory.newBuilder[B] b ++= prefix b ++= this @@ -78,7 +79,7 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] override def diff[B >: A](that: Seq[B]): C = if (isEmpty || that.isEmpty) coll else { - val occ = occCounts(that) + val occ = occCounts[B](that) val b = newSpecificBuilder for (x <- this) { occ.updateWith(x) { @@ -96,7 +97,7 @@ trait StrictOptimizedSeqOps [+A, +CC[_], +C] override def intersect[B >: A](that: Seq[B]): C = if (isEmpty || that.isEmpty) empty else { - val occ = occCounts(that) + val occ = occCounts[B](that) val b = newSpecificBuilder for (x <- this) { occ.updateWith(x) { diff --git a/scala2-library-cc/src/scala/collection/StrictOptimizedSetOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSetOps.scala index 356bd2883578..8ed337fff998 100644 --- a/scala2-library-cc/src/scala/collection/StrictOptimizedSetOps.scala +++ b/scala2-library-cc/src/scala/collection/StrictOptimizedSetOps.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking /** * Trait that overrides set operations to take advantage of strict builders. diff --git a/scala2-library-cc/src/scala/collection/StrictOptimizedSortedMapOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSortedMapOps.scala index 1beaf1662abe..9a9e6e367922 100644 --- a/scala2-library-cc/src/scala/collection/StrictOptimizedSortedMapOps.scala +++ b/scala2-library-cc/src/scala/collection/StrictOptimizedSortedMapOps.scala @@ -13,6 +13,7 @@ package scala.collection import scala.annotation.implicitNotFound +import language.experimental.captureChecking /** * Trait that overrides sorted map operations to take advantage of strict builders. @@ -32,7 +33,7 @@ trait StrictOptimizedSortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOp override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = strictOptimizedFlatMap(sortedMapFactory.newBuilder, f) - override def concat[V2 >: V](xs: IterableOnce[(K, V2)]): CC[K, V2] = + override def concat[V2 >: V](xs: IterableOnce[(K, V2)]^): CC[K, V2] = strictOptimizedConcat(xs, sortedMapFactory.newBuilder(ordering)) override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = diff --git a/scala2-library-cc/src/scala/collection/StringOps.scala b/scala2-library-cc/src/scala/collection/StringOps.scala index f0be485af8ae..f570531def98 100644 --- a/scala2-library-cc/src/scala/collection/StringOps.scala +++ b/scala2-library-cc/src/scala/collection/StringOps.scala @@ -22,6 +22,7 @@ import scala.collection.mutable.StringBuilder import scala.math.{ScalaNumber, max, min} import scala.reflect.ClassTag import scala.util.matching.Regex +import language.experimental.captureChecking object StringOps { // just statics for companion class. @@ -123,7 +124,7 @@ object StringOps { * @return a new collection resulting from applying the given collection-valued function * `f` to each char of this string and concatenating the results. */ - def flatMap[B](f: Char => IterableOnce[B]): immutable.IndexedSeq[B] = { + def flatMap[B](f: Char => IterableOnce[B]^): immutable.IndexedSeq[B] = { val len = s.length val b = immutable.IndexedSeq.newBuilder[B] var i = 0 @@ -155,7 +156,7 @@ object StringOps { } /** Creates a new non-strict filter which combines this filter with the given predicate. */ - def withFilter(q: Char => Boolean): WithFilter = new WithFilter(a => p(a) && q(a), s) + def withFilter(q: Char => Boolean): WithFilter^{p, q} = new WithFilter(a => p(a) && q(a), s) } /** Avoid an allocation in [[collect]]. */ @@ -238,7 +239,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a new collection resulting from applying the given collection-valued function * `f` to each char of this string and concatenating the results. */ - def flatMap[B](f: Char => IterableOnce[B]): immutable.IndexedSeq[B] = { + def flatMap[B](f: Char => IterableOnce[B]^): immutable.IndexedSeq[B] = { val len = s.length val b = immutable.IndexedSeq.newBuilder[B] var i = 0 @@ -313,7 +314,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a new collection which contains all chars * of this string followed by all elements of `suffix`. */ - def concat[B >: Char](suffix: IterableOnce[B]): immutable.IndexedSeq[B] = { + def concat[B >: Char](suffix: IterableOnce[B]^): immutable.IndexedSeq[B] = { val b = immutable.IndexedSeq.newBuilder[B] val k = suffix.knownSize b.sizeHint(s.length + (if(k >= 0) k else 16)) @@ -329,7 +330,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a new string which contains all chars * of this string followed by all chars of `suffix`. */ - def concat(suffix: IterableOnce[Char]): String = { + def concat(suffix: IterableOnce[Char]^): String = { val k = suffix.knownSize val sb = new JStringBuilder(s.length + (if(k >= 0) k else 16)) sb.append(s) @@ -347,10 +348,10 @@ final class StringOps(private val s: String) extends AnyVal { @`inline` def concat(suffix: String): String = s + suffix /** Alias for `concat` */ - @`inline` def ++[B >: Char](suffix: Iterable[B]): immutable.IndexedSeq[B] = concat(suffix) + @`inline` def ++[B >: Char](suffix: Iterable[B]^): immutable.IndexedSeq[B] = concat(suffix) /** Alias for `concat` */ - @`inline` def ++(suffix: IterableOnce[Char]): String = concat(suffix) + @`inline` def ++(suffix: IterableOnce[Char]^): String = concat(suffix) /** Alias for `concat` */ def ++(xs: String): String = concat(xs) @@ -422,7 +423,7 @@ final class StringOps(private val s: String) extends AnyVal { @`inline` def +: (c: Char): String = prepended(c) /** A copy of the string with all elements from a collection prepended */ - def prependedAll[B >: Char](prefix: IterableOnce[B]): immutable.IndexedSeq[B] = { + def prependedAll[B >: Char](prefix: IterableOnce[B]^): immutable.IndexedSeq[B] = { val b = immutable.IndexedSeq.newBuilder[B] val k = prefix.knownSize b.sizeHint(s.length + (if(k >= 0) k else 16)) @@ -432,7 +433,7 @@ final class StringOps(private val s: String) extends AnyVal { } /** Alias for `prependedAll` */ - @`inline` def ++: [B >: Char] (prefix: IterableOnce[B]): immutable.IndexedSeq[B] = prependedAll(prefix) + @`inline` def ++: [B >: Char] (prefix: IterableOnce[B]^): immutable.IndexedSeq[B] = prependedAll(prefix) /** A copy of the string with another string prepended */ def prependedAll(prefix: String): String = prefix + s @@ -460,11 +461,11 @@ final class StringOps(private val s: String) extends AnyVal { @`inline` def :+ (c: Char): String = appended(c) /** A copy of the string with all elements from a collection appended */ - @`inline` def appendedAll[B >: Char](suffix: IterableOnce[B]): immutable.IndexedSeq[B] = + @`inline` def appendedAll[B >: Char](suffix: IterableOnce[B]^): immutable.IndexedSeq[B] = concat(suffix) /** Alias for `appendedAll` */ - @`inline` def :++ [B >: Char](suffix: IterableOnce[B]): immutable.IndexedSeq[B] = + @`inline` def :++ [B >: Char](suffix: IterableOnce[B]^): immutable.IndexedSeq[B] = concat(suffix) /** A copy of the string with another string appended */ @@ -486,7 +487,7 @@ final class StringOps(private val s: String) extends AnyVal { * except that `replaced` chars starting from `from` are replaced * by `other`. */ - def patch[B >: Char](from: Int, other: IterableOnce[B], replaced: Int): immutable.IndexedSeq[B] = { + def patch[B >: Char](from: Int, other: IterableOnce[B]^, replaced: Int): immutable.IndexedSeq[B] = { val len = s.length @`inline` def slc(off: Int, length: Int): WrappedString = new WrappedString(s.substring(off, off+length)) @@ -515,7 +516,7 @@ final class StringOps(private val s: String) extends AnyVal { * by `other`. * @note $unicodeunaware */ - def patch(from: Int, other: IterableOnce[Char], replaced: Int): String = + def patch(from: Int, other: IterableOnce[Char]^, replaced: Int): String = patch(from, other.iterator.mkString, replaced) /** Produces a new string where a slice of characters in this string is replaced by another string. @@ -1195,7 +1196,7 @@ final class StringOps(private val s: String) extends AnyVal { * All these operations apply to those chars of this string * which satisfy the predicate `p`. */ - def withFilter(p: Char => Boolean): StringOps.WithFilter = new StringOps.WithFilter(p, s) + def withFilter(p: Char => Boolean): StringOps.WithFilter^{p} = new StringOps.WithFilter(p, s) /** The rest of the string without its first char. * @note $unicodeunaware @@ -1246,7 +1247,7 @@ final class StringOps(private val s: String) extends AnyVal { def inits: Iterator[String] = iterateUntilEmpty(_.init) // A helper for tails and inits. - private[this] def iterateUntilEmpty(f: String => String): Iterator[String] = + private[this] def iterateUntilEmpty(f: String => String): Iterator[String]^{f} = Iterator.iterate(s)(f).takeWhile(x => !x.isEmpty) ++ Iterator.single("") /** Selects all chars of this string which satisfy a predicate. */ @@ -1464,7 +1465,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a decorator `LazyZip2` that allows strict operations to be performed on the lazily evaluated pairs * or chained calls to `lazyZip`. Implicit conversion to `Iterable[(A, B)]` is also supported. */ - def lazyZip[B](that: Iterable[B]): LazyZip2[Char, B, String] = new LazyZip2(s, new WrappedString(s), that) + def lazyZip[B](that: Iterable[B]^): LazyZip2[Char, B, String]^{that} = new LazyZip2(s, new WrappedString(s), that) /* ************************************************************************************************************ @@ -1512,7 +1513,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a new string consisting of all the chars of this string without duplicates. * @note $unicodeunaware */ - def distinctBy[B](f: Char => B): String = new WrappedString(s).distinctBy(f).unwrap + def distinctBy[B](f: Char -> B): String = new WrappedString(s).distinctBy(f).unwrap /** Sorts the characters of this string according to an Ordering. * diff --git a/scala2-library-cc/src/scala/collection/StringParsers.scala b/scala2-library-cc/src/scala/collection/StringParsers.scala index 5479a58d485f..75dedab7183c 100644 --- a/scala2-library-cc/src/scala/collection/StringParsers.scala +++ b/scala2-library-cc/src/scala/collection/StringParsers.scala @@ -14,6 +14,7 @@ package scala package collection import scala.annotation.tailrec +import language.experimental.captureChecking /** A module containing the implementations of parsers from strings to numeric types, and boolean */ @@ -34,7 +35,7 @@ private[scala] object StringParsers { @inline private[this] final def stepToOverflow(from: String, len: Int, agg: Int, isPositive: Boolean, min: Int): Option[Int] = { @tailrec - def rec(i: Int, agg: Int): Option[Int] = + def rec(i: Int, agg: Int): Option[Int] = if (agg < min) None else if (i == len) { if (!isPositive) Some(agg) @@ -131,11 +132,11 @@ private[scala] object StringParsers { else None } } - + final def parseLong(from: String): Option[Long] = { //like parseInt, but Longer val len = from.length() - + @tailrec def step(i: Int, agg: Long, isPositive: Boolean): Option[Long] = { if (i == len) { @@ -166,7 +167,6 @@ private[scala] object StringParsers { else None } } - //floating point final def checkFloatFormat(format: String): Boolean = { //indices are tracked with a start index which points *at* the first index @@ -192,7 +192,6 @@ private[scala] object StringParsers { else i rec(from) } - def isHexFloatLiteral(startIndex: Int, endIndex: Int): Boolean = { def isHexDigit(ch: Char) = ((ch >= '0' && ch <= '9') || @@ -231,7 +230,6 @@ private[scala] object StringParsers { val pIndex = format.indexWhere(ch => ch == 'p' || ch == 'P', startIndex) (pIndex <= endIndex) && prefixOK(startIndex, pIndex) && postfixOK(pIndex + 1, endIndex) } - def isDecFloatLiteral(startIndex: Int, endIndex: Int): Boolean = { //invariant: endIndex > startIndex @@ -278,7 +276,6 @@ private[scala] object StringParsers { //count 0x00 to 0x20 as "whitespace", and nothing else val unspacedStart = format.indexWhere(ch => ch.toInt > 0x20) val unspacedEnd = format.lastIndexWhere(ch => ch.toInt > 0x20) + 1 - if (unspacedStart == -1 || unspacedStart >= unspacedEnd || unspacedEnd <= 0) false else { //all formats can have a sign @@ -305,7 +302,6 @@ private[scala] object StringParsers { } } } - @inline def parseFloat(from: String): Option[Float] = if (checkFloatFormat(from)) Some(java.lang.Float.parseFloat(from)) diff --git a/scala2-library-cc/src/scala/collection/View.scala b/scala2-library-cc/src/scala/collection/View.scala index 87849744a5dc..8e2ee3ad9e32 100644 --- a/scala2-library-cc/src/scala/collection/View.scala +++ b/scala2-library-cc/src/scala/collection/View.scala @@ -15,6 +15,7 @@ package scala.collection import scala.annotation.{nowarn, tailrec} import scala.collection.mutable.{ArrayBuffer, Builder} import scala.collection.immutable.LazyList +import language.experimental.captureChecking /** Views are collections whose transformation operations are non strict: the resulting elements * are evaluated only when the view is effectively traversed (e.g. using `foreach` or `foldLeft`), @@ -23,8 +24,9 @@ import scala.collection.immutable.LazyList * @define Coll `View` */ trait View[+A] extends Iterable[A] with IterableOps[A, View, View[A]] with IterableFactoryDefaults[A, View] with Serializable { + this: View[A]^ => - override def view: View[A] = this + override def view: View[A]^{this} = this override def iterableFactory: IterableFactory[View] = View @@ -55,8 +57,8 @@ object View extends IterableFactory[View] { * * @tparam A View element type */ - def fromIteratorProvider[A](it: () => Iterator[A]): View[A] = new AbstractView[A] { - def iterator = it() + def fromIteratorProvider[A](it: () => Iterator[A]^): View[A]^{it} = new AbstractView[A] { + def iterator: Iterator[A]^{it} = it() } /** @@ -67,7 +69,7 @@ object View extends IterableFactory[View] { * * @tparam E View element type */ - def from[E](it: IterableOnce[E]): View[E] = it match { + def from[E](it: IterableOnce[E]^): View[E]^{it} = it match { case it: View[E] => it case it: Iterable[E] => View.fromIteratorProvider(() => it.iterator) case _ => LazyList.from(it).view @@ -97,7 +99,7 @@ object View extends IterableFactory[View] { /** A view with given elements */ @SerialVersionUID(3L) - class Elems[A](xs: A*) extends AbstractView[A] { + class Elems[A](xs: A*) extends AbstractView[A], Pure { def iterator = xs.iterator override def knownSize = xs.knownSize override def isEmpty: Boolean = xs.isEmpty @@ -106,7 +108,7 @@ object View extends IterableFactory[View] { /** A view containing the results of some element computation a number of times. */ @SerialVersionUID(3L) class Fill[A](n: Int)(elem: => A) extends AbstractView[A] { - def iterator = Iterator.fill(n)(elem) + def iterator: Iterator[A]^{elem} = Iterator.fill(n)(elem) override def knownSize: Int = 0 max n override def isEmpty: Boolean = n <= 0 } @@ -114,7 +116,7 @@ object View extends IterableFactory[View] { /** A view containing values of a given function over a range of integer values starting from 0. */ @SerialVersionUID(3L) class Tabulate[A](n: Int)(f: Int => A) extends AbstractView[A] { - def iterator: Iterator[A] = Iterator.tabulate(n)(f) + def iterator: Iterator[A]^{f} = Iterator.tabulate(n)(f) override def knownSize: Int = 0 max n override def isEmpty: Boolean = n <= 0 } @@ -122,7 +124,7 @@ object View extends IterableFactory[View] { /** A view containing repeated applications of a function to a start value */ @SerialVersionUID(3L) class Iterate[A](start: A, len: Int)(f: A => A) extends AbstractView[A] { - def iterator: Iterator[A] = Iterator.iterate(start)(f).take(len) + def iterator: Iterator[A]^{f} = Iterator.iterate(start)(f).take(len) override def knownSize: Int = 0 max len override def isEmpty: Boolean = len <= 0 } @@ -132,7 +134,7 @@ object View extends IterableFactory[View] { */ @SerialVersionUID(3L) class Unfold[A, S](initial: S)(f: S => Option[(A, S)]) extends AbstractView[A] { - def iterator: Iterator[A] = Iterator.unfold(initial)(f) + def iterator: Iterator[A]^{f} = Iterator.unfold(initial)(f) } /** An `IterableOps` whose collection type and collection type constructor are unknown */ @@ -140,14 +142,14 @@ object View extends IterableFactory[View] { /** A view that filters an underlying collection. */ @SerialVersionUID(3L) - class Filter[A](val underlying: SomeIterableOps[A], val p: A => Boolean, val isFlipped: Boolean) extends AbstractView[A] { - def iterator = underlying.iterator.filterImpl(p, isFlipped) + class Filter[A](val underlying: SomeIterableOps[A]^, val p: A => Boolean, val isFlipped: Boolean) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying, p} = underlying.iterator.filterImpl(p, isFlipped) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty } object Filter { - def apply[A](underlying: Iterable[A], p: A => Boolean, isFlipped: Boolean): Filter[A] = + def apply[A](underlying: Iterable[A]^, p: A => Boolean, isFlipped: Boolean): Filter[A]^{underlying, p} = underlying match { case filter: Filter[A] if filter.isFlipped == isFlipped => new Filter(filter.underlying, a => filter.p(a) && p(a), isFlipped) case _ => new Filter(underlying, p, isFlipped) @@ -156,15 +158,15 @@ object View extends IterableFactory[View] { /** A view that removes the duplicated elements as determined by the transformation function `f` */ @SerialVersionUID(3L) - class DistinctBy[A, B](underlying: SomeIterableOps[A], f: A => B) extends AbstractView[A] { - def iterator: Iterator[A] = underlying.iterator.distinctBy(f) + class DistinctBy[A, B](underlying: SomeIterableOps[A]^, f: A -> B) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = underlying.iterator.distinctBy(f) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) - class LeftPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A], f: A => Either[A1, A2]) extends AbstractView[A1] { - def iterator: AbstractIterator[A1] = new AbstractIterator[A1] { + class LeftPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A]^, f: A => Either[A1, A2]) extends AbstractView[A1] { + def iterator: Iterator[A1]^{underlying, f} = new AbstractIterator[A1] { private[this] val self = underlying.iterator private[this] var hd: A1 = _ private[this] var hdDefined: Boolean = false @@ -188,8 +190,8 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - class RightPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A], f: A => Either[A1, A2]) extends AbstractView[A2] { - def iterator: AbstractIterator[A2] = new AbstractIterator[A2] { + class RightPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A]^, f: A => Either[A1, A2]) extends AbstractView[A2] { + def iterator: Iterator[A2]^{this} = new AbstractIterator[A2] { private[this] val self = underlying.iterator private[this] var hd: A2 = _ private[this] var hdDefined: Boolean = false @@ -214,8 +216,8 @@ object View extends IterableFactory[View] { /** A view that drops leading elements of the underlying collection. */ @SerialVersionUID(3L) - class Drop[A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { - def iterator = underlying.iterator.drop(n) + class Drop[A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = underlying.iterator.drop(n) protected val normN = n max 0 override def knownSize = { val size = underlying.knownSize @@ -226,8 +228,8 @@ object View extends IterableFactory[View] { /** A view that drops trailing elements of the underlying collection. */ @SerialVersionUID(3L) - class DropRight[A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { - def iterator = dropRightIterator(underlying.iterator, n) + class DropRight[A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = dropRightIterator(underlying.iterator, n) protected val normN = n max 0 override def knownSize = { val size = underlying.knownSize @@ -239,16 +241,16 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - class DropWhile[A](underlying: SomeIterableOps[A], p: A => Boolean) extends AbstractView[A] { - def iterator = underlying.iterator.dropWhile(p) + class DropWhile[A](underlying: SomeIterableOps[A]^, p: A => Boolean) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying, p} = underlying.iterator.dropWhile(p) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty } /** A view that takes leading elements of the underlying collection. */ @SerialVersionUID(3L) - class Take[+A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { - def iterator = underlying.iterator.take(n) + class Take[+A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = underlying.iterator.take(n) protected val normN = n max 0 override def knownSize = { val size = underlying.knownSize @@ -259,8 +261,8 @@ object View extends IterableFactory[View] { /** A view that takes trailing elements of the underlying collection. */ @SerialVersionUID(3L) - class TakeRight[+A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { - def iterator = takeRightIterator(underlying.iterator, n) + class TakeRight[+A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = takeRightIterator(underlying.iterator, n) protected val normN = n max 0 override def knownSize = { val size = underlying.knownSize @@ -272,15 +274,15 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - class TakeWhile[A](underlying: SomeIterableOps[A], p: A => Boolean) extends AbstractView[A] { - def iterator: Iterator[A] = underlying.iterator.takeWhile(p) + class TakeWhile[A](underlying: SomeIterableOps[A]^, p: A => Boolean) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying, p} = underlying.iterator.takeWhile(p) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) - class ScanLeft[+A, +B](underlying: SomeIterableOps[A], z: B, op: (B, A) => B) extends AbstractView[B] { - def iterator: Iterator[B] = underlying.iterator.scanLeft(z)(op) + class ScanLeft[+A, +B](underlying: SomeIterableOps[A]^, z: B, op: (B, A) => B) extends AbstractView[B] { + def iterator: Iterator[B]^{underlying, op} = underlying.iterator.scanLeft(z)(op) override def knownSize: Int = { val size = underlying.knownSize if (size >= 0) size + 1 else -1 @@ -290,32 +292,32 @@ object View extends IterableFactory[View] { /** A view that maps elements of the underlying collection. */ @SerialVersionUID(3L) - class Map[+A, +B](underlying: SomeIterableOps[A], f: A => B) extends AbstractView[B] { - def iterator = underlying.iterator.map(f) + class Map[+A, +B](underlying: SomeIterableOps[A]^, f: A => B) extends AbstractView[B] { + def iterator: Iterator[B]^{underlying, f} = underlying.iterator.map(f) override def knownSize = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } /** A view that flatmaps elements of the underlying collection. */ @SerialVersionUID(3L) - class FlatMap[A, B](underlying: SomeIterableOps[A], f: A => IterableOnce[B]) extends AbstractView[B] { - def iterator = underlying.iterator.flatMap(f) + class FlatMap[A, B](underlying: SomeIterableOps[A]^, f: A => IterableOnce[B]^) extends AbstractView[B] { + def iterator: Iterator[B]^{underlying, f} = underlying.iterator.flatMap(f) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty } /** A view that collects elements of the underlying collection. */ @SerialVersionUID(3L) - class Collect[+A, B](underlying: SomeIterableOps[A], pf: PartialFunction[A, B]) extends AbstractView[B] { - def iterator = underlying.iterator.collect(pf) + class Collect[+A, B](underlying: SomeIterableOps[A]^, pf: PartialFunction[A, B]^) extends AbstractView[B] { + def iterator: Iterator[B]^{underlying, pf} = underlying.iterator.collect(pf) } /** A view that concatenates elements of the prefix collection or iterator with the elements * of the suffix collection or iterator. */ @SerialVersionUID(3L) - class Concat[A](prefix: SomeIterableOps[A], suffix: SomeIterableOps[A]) extends AbstractView[A] { - def iterator = prefix.iterator ++ suffix.iterator + class Concat[A](prefix: SomeIterableOps[A]^, suffix: SomeIterableOps[A]^) extends AbstractView[A] { + def iterator: Iterator[A]^{prefix, suffix} = prefix.iterator ++ suffix.iterator override def knownSize = { val prefixSize = prefix.knownSize if (prefixSize >= 0) { @@ -332,8 +334,8 @@ object View extends IterableFactory[View] { * of another collection. */ @SerialVersionUID(3L) - class Zip[A, B](underlying: SomeIterableOps[A], other: Iterable[B]) extends AbstractView[(A, B)] { - def iterator = underlying.iterator.zip(other) + class Zip[A, B](underlying: SomeIterableOps[A]^, other: Iterable[B]^) extends AbstractView[(A, B)] { + def iterator: Iterator[(A, B)]^{underlying, other} = underlying.iterator.zip(other) override def knownSize = { val s1 = underlying.knownSize if (s1 == 0) 0 else { @@ -349,8 +351,8 @@ object View extends IterableFactory[View] { * placeholder elements are used to extend the shorter collection to the length of the longer. */ @SerialVersionUID(3L) - class ZipAll[A, B](underlying: SomeIterableOps[A], other: Iterable[B], thisElem: A, thatElem: B) extends AbstractView[(A, B)] { - def iterator = underlying.iterator.zipAll(other, thisElem, thatElem) + class ZipAll[A, B](underlying: SomeIterableOps[A]^, other: Iterable[B]^, thisElem: A, thatElem: B) extends AbstractView[(A, B)] { + def iterator: Iterator[(A, B)]^{underlying, other} = underlying.iterator.zipAll(other, thisElem, thatElem) override def knownSize = { val s1 = underlying.knownSize if(s1 == -1) -1 else { @@ -363,8 +365,10 @@ object View extends IterableFactory[View] { /** A view that appends an element to its elements */ @SerialVersionUID(3L) - class Appended[+A](underlying: SomeIterableOps[A], elem: A) extends AbstractView[A] { - def iterator: Iterator[A] = new Concat(underlying, new View.Single(elem)).iterator + class Appended[+A](underlying: SomeIterableOps[A]^, elem: A) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = + val ct = new Concat(underlying, new View.Single(elem)) + ct.iterator // CC TODO breakout into `ct` needed, otherwise "cannot establish a reference" error override def knownSize: Int = { val size = underlying.knownSize if (size >= 0) size + 1 else -1 @@ -374,8 +378,10 @@ object View extends IterableFactory[View] { /** A view that prepends an element to its elements */ @SerialVersionUID(3L) - class Prepended[+A](elem: A, underlying: SomeIterableOps[A]) extends AbstractView[A] { - def iterator: Iterator[A] = new Concat(new View.Single(elem), underlying).iterator + class Prepended[+A](elem: A, underlying: SomeIterableOps[A]^) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = + val ct = new Concat(new View.Single(elem), underlying) + ct.iterator // CC TODO breakout into `ct` needed, otherwise "cannot establish a reference" error override def knownSize: Int = { val size = underlying.knownSize if (size >= 0) size + 1 else -1 @@ -384,8 +390,8 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - class Updated[A](underlying: SomeIterableOps[A], index: Int, elem: A) extends AbstractView[A] { - def iterator: Iterator[A] = new AbstractIterator[A] { + class Updated[A](underlying: SomeIterableOps[A]^, index: Int, elem: A) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = new AbstractIterator[A] { private[this] val it = underlying.iterator private[this] var i = 0 def next(): A = { @@ -403,28 +409,28 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - private[collection] class Patched[A](underlying: SomeIterableOps[A], from: Int, other: IterableOnce[A], replaced: Int) extends AbstractView[A] { + private[collection] class Patched[A](underlying: SomeIterableOps[A]^, from: Int, other: IterableOnce[A]^, replaced: Int) extends AbstractView[A] { // we may be unable to traverse `other` more than once, so we need to cache it if that's the case - private val _other: Iterable[A] = other match { + private val _other: Iterable[A]^{other} = other match { case other: Iterable[A] => other case other => LazyList.from(other) } - def iterator: Iterator[A] = underlying.iterator.patch(from, _other.iterator, replaced) + def iterator: Iterator[A]^{underlying, other} = underlying.iterator.patch(from, _other.iterator, replaced) override def knownSize: Int = if (underlying.knownSize == 0 && _other.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = if (knownSize == 0) true else iterator.isEmpty } @SerialVersionUID(3L) - class ZipWithIndex[A](underlying: SomeIterableOps[A]) extends AbstractView[(A, Int)] { - def iterator: Iterator[(A, Int)] = underlying.iterator.zipWithIndex + class ZipWithIndex[A](underlying: SomeIterableOps[A]^) extends AbstractView[(A, Int)] { + def iterator: Iterator[(A, Int)]^{underlying} = underlying.iterator.zipWithIndex override def knownSize: Int = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) - class PadTo[A](underlying: SomeIterableOps[A], len: Int, elem: A) extends AbstractView[A] { - def iterator: Iterator[A] = underlying.iterator.padTo(len, elem) + class PadTo[A](underlying: SomeIterableOps[A]^, len: Int, elem: A) extends AbstractView[A] { + def iterator: Iterator[A]^{underlying} = underlying.iterator.padTo(len, elem) override def knownSize: Int = { val size = underlying.knownSize @@ -433,7 +439,7 @@ object View extends IterableFactory[View] { override def isEmpty: Boolean = underlying.isEmpty && len <= 0 } - private[collection] def takeRightIterator[A](it: Iterator[A], n: Int): Iterator[A] = { + private[collection] def takeRightIterator[A](it: Iterator[A]^, n: Int): Iterator[A]^{it} = { val k = it.knownSize if(k == 0 || n <= 0) Iterator.empty else if(n == Int.MaxValue) it @@ -441,22 +447,23 @@ object View extends IterableFactory[View] { else new TakeRightIterator[A](it, n) } - private final class TakeRightIterator[A](private[this] var underlying: Iterator[A], maxlen: Int) extends AbstractIterator[A] { + private final class TakeRightIterator[A](underlying: Iterator[A]^, maxlen: Int) extends AbstractIterator[A] { + private[this] var current: Iterator[A]^{underlying} = underlying private[this] var len: Int = -1 private[this] var pos: Int = 0 private[this] var buf: ArrayBuffer[AnyRef] = _ def init(): Unit = if(buf eq null) { buf = new ArrayBuffer[AnyRef](maxlen min 256) len = 0 - while(underlying.hasNext) { - val n = underlying.next().asInstanceOf[AnyRef] + while(current.hasNext) { + val n = current.next().asInstanceOf[AnyRef] if(pos >= buf.length) buf.addOne(n) else buf(pos) = n pos += 1 if(pos == maxlen) pos = 0 len += 1 } - underlying = null + current = null if(len > maxlen) len = maxlen pos = pos - len if(pos < 0) pos += maxlen @@ -477,7 +484,7 @@ object View extends IterableFactory[View] { x } } - override def drop(n: Int): Iterator[A] = { + override def drop(n: Int): Iterator[A]^{this} = { init() if (n > 0) { len = (len - n) max 0 @@ -487,7 +494,7 @@ object View extends IterableFactory[View] { } } - private[collection] def dropRightIterator[A](it: Iterator[A], n: Int): Iterator[A] = { + private[collection] def dropRightIterator[A](it: Iterator[A]^, n: Int): Iterator[A]^{it} = { if(n <= 0) it else { val k = it.knownSize @@ -496,7 +503,7 @@ object View extends IterableFactory[View] { } } - private final class DropRightIterator[A](private[this] var underlying: Iterator[A], maxlen: Int) extends AbstractIterator[A] { + private final class DropRightIterator[A](underlying: Iterator[A]^, maxlen: Int) extends AbstractIterator[A] { private[this] var len: Int = -1 // known size or -1 if the end of `underlying` has not been seen yet private[this] var pos: Int = 0 private[this] var buf: ArrayBuffer[AnyRef] = _ diff --git a/scala2-library-cc/src/scala/collection/WithFilter.scala b/scala2-library-cc/src/scala/collection/WithFilter.scala index 4699abbef5a7..0f3830e9fe25 100644 --- a/scala2-library-cc/src/scala/collection/WithFilter.scala +++ b/scala2-library-cc/src/scala/collection/WithFilter.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking /** A template trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods * of trait `Iterable`. @@ -22,6 +23,7 @@ package scala.collection */ @SerialVersionUID(3L) abstract class WithFilter[+A, +CC[_]] extends Serializable { + this: WithFilter[A, CC]^ => /** Builds a new collection by applying a function to all elements of the * `filtered` outer $coll. @@ -32,7 +34,7 @@ abstract class WithFilter[+A, +CC[_]] extends Serializable { * the given function `f` to each element of the filtered outer $coll * and collecting the results. */ - def map[B](f: A => B): CC[B] + def map[B](f: A => B): CC[B]^{this, f} /** Builds a new collection by applying a function to all elements of the * `filtered` outer $coll containing this `WithFilter` instance that satisfy @@ -44,7 +46,7 @@ abstract class WithFilter[+A, +CC[_]] extends Serializable { * of the filtered outer $coll and * concatenating the results. */ - def flatMap[B](f: A => IterableOnce[B]): CC[B] + def flatMap[B](f: A => IterableOnce[B]^): CC[B]^{this, f} /** Applies a function `f` to all elements of the `filtered` outer $coll. * @@ -65,6 +67,6 @@ abstract class WithFilter[+A, +CC[_]] extends Serializable { * All these operations apply to those elements of this $coll which * also satisfy both `p` and `q` predicates. */ - def withFilter(q: A => Boolean): WithFilter[A, CC] + def withFilter(q: A => Boolean): WithFilter[A, CC]^{this, q} } diff --git a/scala2-library-cc/src/scala/collection/concurrent/Map.scala b/scala2-library-cc/src/scala/collection/concurrent/Map.scala index c2b996b93102..d985dad2edc5 100644 --- a/scala2-library-cc/src/scala/collection/concurrent/Map.scala +++ b/scala2-library-cc/src/scala/collection/concurrent/Map.scala @@ -13,6 +13,7 @@ package scala package collection.concurrent +import language.experimental.captureChecking import scala.annotation.tailrec /** A template trait for mutable maps that allow concurrent access. diff --git a/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala b/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala index 7474d56cf311..8a34eddf0bdb 100644 --- a/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala +++ b/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala @@ -23,6 +23,7 @@ import scala.collection.immutable.{List, Nil} import scala.collection.mutable.GrowableBuilder import scala.util.Try import scala.util.hashing.Hashing +import language.experimental.captureChecking private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen, equiv: Equiv[K]) extends INodeBase[K, V](g) { import INodeBase._ @@ -438,7 +439,7 @@ private[concurrent] object INode { private[concurrent] final class FailedNode[K, V](p: MainNode[K, V]) extends MainNode[K, V] { WRITE_PREV(p) - def string(lev: Int): Nothing = throw new UnsupportedOperationException + def string(lev: Int) = throw new UnsupportedOperationException def cachedSize(ct: AnyRef): Int = throw new UnsupportedOperationException @@ -1017,10 +1018,10 @@ final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater override def view: MapView[K, V] = if (nonReadOnly) readOnlySnapshot().view else super.view @deprecated("Use .view.filterKeys(f). A future version will include a strict version of this method (for now, .view.filterKeys(p).toMap).", "2.13.0") - override def filterKeys(p: K => Boolean): collection.MapView[K, V] = view.filterKeys(p) + override def filterKeys(p: K => Boolean): collection.MapView[K, V]^{p} = view.filterKeys(p) @deprecated("Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).", "2.13.0") - override def mapValues[W](f: V => W): collection.MapView[K, W] = view.mapValues(f) + override def mapValues[W](f: V => W): collection.MapView[K, W]^{f} = view.mapValues(f) // END extra overrides /////////////////////////////////////////////////////////////////// @@ -1043,7 +1044,7 @@ object TrieMap extends MapFactory[TrieMap] { def empty[K, V]: TrieMap[K, V] = new TrieMap[K, V] - def from[K, V](it: IterableOnce[(K, V)]): TrieMap[K, V] = new TrieMap[K, V]() ++= it + def from[K, V](it: IterableOnce[(K, V)]^): TrieMap[K, V] = new TrieMap[K, V]() ++= it def newBuilder[K, V]: mutable.GrowableBuilder[(K, V), TrieMap[K, V]] = new GrowableBuilder(empty[K, V]) @@ -1182,7 +1183,10 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: stack(d) = arr1 stackpos(d) = -1 val it = newIterator(level + 1, ct, _mustInit = false) - it.stack(0) = arr2 + val xss: Array[Array[BasicNode]] = it.stack.asInstanceOf + // !!! cc split into separate xss and asInstanceOf needed because cc gets confused with + // two-dimensinal invariant arrays + xss(0) = arr2 it.stackpos(0) = -1 it.depth = 0 it.advance() // <-- fix it diff --git a/scala2-library-cc/src/scala/collection/convert/AsJavaConverters.scala b/scala2-library-cc/src/scala/collection/convert/AsJavaConverters.scala index 3d155337aa93..bfae792c5107 100644 --- a/scala2-library-cc/src/scala/collection/convert/AsJavaConverters.scala +++ b/scala2-library-cc/src/scala/collection/convert/AsJavaConverters.scala @@ -18,6 +18,7 @@ import java.util.{concurrent => juc} import java.{lang => jl, util => ju} import scala.{unchecked => uc} +import language.experimental.captureChecking /** Defines converter methods from Scala to Java collections. * These methods are available through the [[scala.jdk.javaapi.CollectionConverters]] object. diff --git a/scala2-library-cc/src/scala/collection/convert/AsJavaExtensions.scala b/scala2-library-cc/src/scala/collection/convert/AsJavaExtensions.scala index 16b15c513a17..14268f7aa165 100644 --- a/scala2-library-cc/src/scala/collection/convert/AsJavaExtensions.scala +++ b/scala2-library-cc/src/scala/collection/convert/AsJavaExtensions.scala @@ -16,6 +16,7 @@ package convert import java.util.{concurrent => juc} import java.{lang => jl, util => ju} +import language.experimental.captureChecking /** Defines `asJava` extension methods, available through [[scala.jdk.CollectionConverters]]. */ trait AsJavaExtensions { diff --git a/scala2-library-cc/src/scala/collection/convert/AsScalaConverters.scala b/scala2-library-cc/src/scala/collection/convert/AsScalaConverters.scala index 30a28ae38147..6cc02b13bb06 100644 --- a/scala2-library-cc/src/scala/collection/convert/AsScalaConverters.scala +++ b/scala2-library-cc/src/scala/collection/convert/AsScalaConverters.scala @@ -18,6 +18,7 @@ import java.util.{concurrent => juc} import java.{lang => jl, util => ju} import scala.{unchecked => uc} +import language.experimental.captureChecking /** Defines converter methods from Java to Scala collections. * These methods are available through the [[scala.jdk.javaapi.CollectionConverters]] object. diff --git a/scala2-library-cc/src/scala/collection/convert/AsScalaExtensions.scala b/scala2-library-cc/src/scala/collection/convert/AsScalaExtensions.scala index 39347dde903b..d60bfc7f60a1 100644 --- a/scala2-library-cc/src/scala/collection/convert/AsScalaExtensions.scala +++ b/scala2-library-cc/src/scala/collection/convert/AsScalaExtensions.scala @@ -16,6 +16,7 @@ package convert import java.util.{concurrent => juc} import java.{lang => jl, util => ju} +import language.experimental.captureChecking /** Defines `asScala` extension methods, available through [[scala.jdk.CollectionConverters]]. */ trait AsScalaExtensions { diff --git a/scala2-library-cc/src/scala/collection/convert/ImplicitConversions.scala b/scala2-library-cc/src/scala/collection/convert/ImplicitConversions.scala index 05d63f9fdeee..1bc284462ff1 100644 --- a/scala2-library-cc/src/scala/collection/convert/ImplicitConversions.scala +++ b/scala2-library-cc/src/scala/collection/convert/ImplicitConversions.scala @@ -19,6 +19,7 @@ import java.{lang => jl, util => ju} import scala.collection.JavaConverters._ import scala.language.implicitConversions +import language.experimental.captureChecking /** Defines implicit converter methods from Java to Scala collections. */ @deprecated("Use `scala.jdk.CollectionConverters` instead", "2.13.0") diff --git a/scala2-library-cc/src/scala/collection/convert/JavaCollectionWrappers.scala b/scala2-library-cc/src/scala/collection/convert/JavaCollectionWrappers.scala index 9f6eb2c25551..e826bdeb23db 100644 --- a/scala2-library-cc/src/scala/collection/convert/JavaCollectionWrappers.scala +++ b/scala2-library-cc/src/scala/collection/convert/JavaCollectionWrappers.scala @@ -22,6 +22,8 @@ import scala.jdk.CollectionConverters._ import scala.util.Try import scala.util.chaining._ import scala.util.control.ControlThrowable +import language.experimental.captureChecking +import annotation.unchecked.uncheckedCaptures /** Wrappers for exposing Scala collections as Java collections and vice-versa */ @SerialVersionUID(3L) @@ -33,50 +35,37 @@ private[collection] object JavaCollectionWrappers extends Serializable { def next() = underlying.next() def hasMoreElements = underlying.hasNext def nextElement() = underlying.next() - override def remove(): Nothing = throw new UnsupportedOperationException - override def equals(other: Any): Boolean = other match { - case that: IteratorWrapper[_] => this.underlying == that.underlying - case _ => false - } - override def hashCode: Int = underlying.hashCode() + override def remove() = throw new UnsupportedOperationException } @SerialVersionUID(3L) - class JIteratorWrapper[A](val underlying: ju.Iterator[A]) extends AbstractIterator[A] with Serializable { + class JIteratorWrapper[A](val underlying: ju.Iterator[A]) extends AbstractIterator[A] with Iterator[A] with Serializable { def hasNext = underlying.hasNext def next() = underlying.next - override def equals(other: Any): Boolean = other match { - case that: JIteratorWrapper[_] => this.underlying == that.underlying - case _ => false - } - override def hashCode: Int = underlying.hashCode() } @SerialVersionUID(3L) - class JEnumerationWrapper[A](val underlying: ju.Enumeration[A]) extends AbstractIterator[A] with Serializable { + class JEnumerationWrapper[A](val underlying: ju.Enumeration[A]) extends AbstractIterator[A] with Iterator[A] with Serializable { def hasNext = underlying.hasMoreElements def next() = underlying.nextElement - override def equals(other: Any): Boolean = other match { - case that: JEnumerationWrapper[_] => this.underlying == that.underlying - case _ => false - } - override def hashCode: Int = underlying.hashCode() } trait IterableWrapperTrait[A] extends ju.AbstractCollection[A] { val underlying: Iterable[A] def size = underlying.size - override def iterator: IteratorWrapper[A] = new IteratorWrapper(underlying.iterator) + override def iterator = new IteratorWrapper(underlying.iterator) override def isEmpty = underlying.isEmpty } @SerialVersionUID(3L) class IterableWrapper[A](val underlying: Iterable[A]) extends ju.AbstractCollection[A] with IterableWrapperTrait[A] with Serializable { - override def equals(other: Any): Boolean = other match { - case that: IterableWrapper[_] => this.underlying == that.underlying - case _ => false - } - override def hashCode: Int = underlying.hashCode() + import scala.runtime.Statics._ + override def equals(other: Any): Boolean = + other match { + case other: IterableWrapper[_] => underlying.equals(other.underlying) + case _ => false + } + override def hashCode = finalizeHash(mix(mix(0xcafebabe, "IterableWrapper".hashCode), anyHash(underlying)), 1) } @SerialVersionUID(3L) @@ -85,13 +74,8 @@ private[collection] object JavaCollectionWrappers extends Serializable { with StrictOptimizedIterableOps[A, Iterable, Iterable[A]] with Serializable { def iterator = underlying.iterator.asScala - override def iterableFactory: mutable.ArrayBuffer.type = mutable.ArrayBuffer + override def iterableFactory = mutable.ArrayBuffer override def isEmpty: Boolean = !underlying.iterator().hasNext - override def equals(other: Any): Boolean = other match { - case that: JIterableWrapper[_] => this.underlying == that.underlying - case _ => false - } - override def hashCode: Int = underlying.hashCode() } @SerialVersionUID(3L) @@ -103,12 +87,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { override def size = underlying.size override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize override def isEmpty = underlying.isEmpty - override def iterableFactory: mutable.ArrayBuffer.type = mutable.ArrayBuffer - override def equals(other: Any): Boolean = other match { - case that: JCollectionWrapper[_] => this.underlying == that.underlying - case _ => false - } - override def hashCode: Int = underlying.hashCode() + override def iterableFactory = mutable.ArrayBuffer } @SerialVersionUID(3L) @@ -150,7 +129,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { def prepend(elem: A) = { underlying.subList(0, 0) add elem; this } def addOne(elem: A): this.type = { underlying add elem; this } def insert(idx: Int,elem: A): Unit = underlying.subList(0, idx).add(elem) - def insertAll(i: Int, elems: IterableOnce[A]) = { + def insertAll(i: Int, elems: IterableOnce[A]^) = { val ins = underlying.subList(0, i) elems.iterator.foreach(ins.add(_)) } @@ -159,13 +138,13 @@ private[collection] object JavaCollectionWrappers extends Serializable { // Note: Clone cannot just call underlying.clone because in Java, only specific collections // expose clone methods. Generically, they're protected. override def clone(): JListWrapper[A] = new JListWrapper(new ju.ArrayList[A](underlying)) - def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type = { + def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A]^, replaced: Int): this.type = { remove(from, replaced) insertAll(from, patch) this } def remove(from: Int, n: Int): Unit = underlying.subList(from, from+n).clear() - override def iterableFactory: mutable.ArrayBuffer.type = mutable.ArrayBuffer + override def iterableFactory = mutable.ArrayBuffer override def subtractOne(elem: A): this.type = { underlying.remove(elem.asInstanceOf[AnyRef]); this } } @@ -178,7 +157,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { } override def isEmpty = underlying.isEmpty def size = underlying.size - def iterator: ju.Iterator[A] = new ju.Iterator[A] { + def iterator = new ju.Iterator[A] { val ui = underlying.iterator var prev: Option[A] = None def hasNext = ui.hasNext @@ -264,13 +243,13 @@ private[collection] object JavaCollectionWrappers extends Serializable { override def entrySet: ju.Set[ju.Map.Entry[K, V]] = new ju.AbstractSet[ju.Map.Entry[K, V]] { def size = self.size - def iterator: ju.Iterator[ju.Map.Entry[K, V]] = new ju.Iterator[ju.Map.Entry[K, V]] { + def iterator = new ju.Iterator[ju.Map.Entry[K, V]] { val ui = underlying.iterator var prev : Option[K] = None def hasNext = ui.hasNext - def next(): ju.Map.Entry[K, V] = { + def next() = { val (k, v) = ui.next() prev = Some(k) new ju.Map.Entry[K, V] { @@ -381,7 +360,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { val result = underlying.put(k, v) if (present) Some(result) else None } else { - var result: Option[V] = None + var result: Option[V @uncheckedCaptures] = None def recompute(k0: K, v0: V): V = v.tap(_ => if (v0 != null) result = Some(v0) else if (underlying.containsKey(k0)) result = Some(null.asInstanceOf[V]) @@ -407,7 +386,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { // support Some(null) if currently bound to null override def remove(k: K): Option[V] = { - var result: Option[V] = None + var result: Option[V @uncheckedCaptures] = None def recompute(k0: K, v0: V): V = { if (v0 != null) result = Some(v0) else if (underlying.containsKey(k0)) result = Some(null.asInstanceOf[V]) @@ -448,7 +427,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { override def isEmpty: Boolean = underlying.isEmpty override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize - override def empty: JMapWrapper[K, V] = new JMapWrapper(new ju.HashMap[K, V]) + override def empty = new JMapWrapper(new ju.HashMap[K, V]) } @SerialVersionUID(3L) @@ -495,7 +474,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { override def isEmpty: Boolean = underlying.isEmpty override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize - override def empty: JConcurrentMapWrapper[K, V] = new JConcurrentMapWrapper(new juc.ConcurrentHashMap[K, V]) + override def empty = new JConcurrentMapWrapper(new juc.ConcurrentHashMap[K, V]) def putIfAbsent(k: K, v: V): Option[V] = Option(underlying.putIfAbsent(k, v)) @@ -552,13 +531,6 @@ private[collection] object JavaCollectionWrappers extends Serializable { } catch { case ex: ClassCastException => null.asInstanceOf[V] } - - override def equals(other: Any): Boolean = other match { - case that: DictionaryWrapper[_, _] => this.underlying == that.underlying - case _ => false - } - - override def hashCode: Int = underlying.hashCode() } @SerialVersionUID(3L) @@ -581,7 +553,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { override def clear() = iterator.foreach(entry => underlying.remove(entry._1)) - override def mapFactory: mutable.HashMap.type = mutable.HashMap + override def mapFactory = mutable.HashMap } @SerialVersionUID(3L) @@ -626,7 +598,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { override def clear() = underlying.clear() - override def empty: JPropertiesWrapper = new JPropertiesWrapper(new ju.Properties) + override def empty = new JPropertiesWrapper(new ju.Properties) def getProperty(key: String) = underlying.getProperty(key) @@ -636,7 +608,7 @@ private[collection] object JavaCollectionWrappers extends Serializable { def setProperty(key: String, value: String) = underlying.setProperty(key, value) - override def mapFactory: mutable.HashMap.type = mutable.HashMap + override def mapFactory = mutable.HashMap } /** Thrown when certain Map operations attempt to put a null value. */ diff --git a/scala2-library-cc/src/scala/collection/convert/StreamExtensions.scala b/scala2-library-cc/src/scala/collection/convert/StreamExtensions.scala index cdeea62fb5ed..ddda95707881 100644 --- a/scala2-library-cc/src/scala/collection/convert/StreamExtensions.scala +++ b/scala2-library-cc/src/scala/collection/convert/StreamExtensions.scala @@ -22,6 +22,7 @@ import scala.collection._ import scala.collection.convert.StreamExtensions.{AccumulatorFactoryInfo, StreamShape, StreamUnboxer} import scala.jdk.CollectionConverters._ import scala.jdk._ +import language.experimental.captureChecking /** Defines extension methods to create Java Streams for Scala collections, available through * [[scala.jdk.javaapi.StreamConverters]]. diff --git a/scala2-library-cc/src/scala/collection/convert/impl/ArrayStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/ArrayStepper.scala index 845ecb4a606d..ba51c7a5a353 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/ArrayStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/ArrayStepper.scala @@ -14,6 +14,7 @@ package scala.collection.convert package impl import scala.collection._ +// import language.experimental.captureChecking // TODO enable private[collection] class ObjectArrayStepper[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends IndexedStepperBase[AnyStepper[A], ObjectArrayStepper[A]](_i0, _iN) diff --git a/scala2-library-cc/src/scala/collection/convert/impl/BinaryTreeStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/BinaryTreeStepper.scala index 7c795aea5391..8b2f604b0977 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/BinaryTreeStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/BinaryTreeStepper.scala @@ -18,6 +18,7 @@ import java.util.Spliterator import annotation.tailrec import scala.collection.Stepper.EfficientSplit import scala.collection._ +// import language.experimental.captureChecking // TODO enable private[collection] object BinaryTreeStepper { @@ -125,7 +126,7 @@ extends EfficientSplit { if (!hasStep || index < 0) null else { val root = stack(0).asInstanceOf[T] - val leftStack = + val leftStack = if (index > 0) java.util.Arrays.copyOfRange(stack, 1, index+1) else BinaryTreeStepper.emptyStack val leftIndex = index - 1 diff --git a/scala2-library-cc/src/scala/collection/convert/impl/BitSetStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/BitSetStepper.scala index 574e7fd50f1c..16801089c39f 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/BitSetStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/BitSetStepper.scala @@ -15,11 +15,12 @@ package impl import scala.collection.Stepper.EfficientSplit import scala.collection.{BitSetOps, IntStepper, Stepper} +// import language.experimental.captureChecking // TODO enable private[collection] final class BitSetStepper( - private var underlying: BitSetOps[_], - private var cache0: Long, private var cache1: Long, + private var underlying: BitSetOps[_], + private var cache0: Long, private var cache1: Long, _i0: Int, _iN: Int, private var cacheIndex: Int ) @@ -47,7 +48,7 @@ with IntStepper { findNext() } } - else if (underlying eq null) { + else if (underlying eq null) { i0 = iN found = false found @@ -96,7 +97,7 @@ with IntStepper { else scanLong(bits, from + 1) def nextStep(): Int = - if (found || findNext()) { + if (found || findNext()) { found = false val ans = i0 i0 += 1 diff --git a/scala2-library-cc/src/scala/collection/convert/impl/ChampStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/ChampStepper.scala index 466e6c440f45..12fb471ea768 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/ChampStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/ChampStepper.scala @@ -16,6 +16,7 @@ package impl import scala.collection.Stepper.EfficientSplit import scala.collection._ import scala.collection.immutable.Node +// import language.experimental.captureChecking // TODO enable /** A stepper that is a slightly elaborated version of the ChampBaseIterator; * the main difference is that it knows when it should stop instead of running diff --git a/scala2-library-cc/src/scala/collection/convert/impl/InOrderStepperBase.scala b/scala2-library-cc/src/scala/collection/convert/impl/InOrderStepperBase.scala index 2d1f88d02930..7140c7d673d0 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/InOrderStepperBase.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/InOrderStepperBase.scala @@ -16,6 +16,7 @@ package impl import java.util.Spliterator import scala.collection.Stepper.EfficientSplit +// import language.experimental.captureChecking // TODO enable /** Abstracts all the generic operations of stepping over a collection * that has an indexable ordering but may have gaps. diff --git a/scala2-library-cc/src/scala/collection/convert/impl/IndexedSeqStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/IndexedSeqStepper.scala index 136ac8d2dcc3..1e2983fde50d 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/IndexedSeqStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/IndexedSeqStepper.scala @@ -14,6 +14,7 @@ package scala.collection.convert package impl import scala.collection._ +// import language.experimental.captureChecking // TODO enable private[collection] class AnyIndexedSeqStepper[A](underlying: collection.IndexedSeqOps[A, AnyConstr, _], _i0: Int, _iN: Int) extends IndexedStepperBase[AnyStepper[A], AnyIndexedSeqStepper[A]](_i0, _iN) diff --git a/scala2-library-cc/src/scala/collection/convert/impl/IndexedStepperBase.scala b/scala2-library-cc/src/scala/collection/convert/impl/IndexedStepperBase.scala index 4670ccc56bfc..cae3809ab077 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/IndexedStepperBase.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/IndexedStepperBase.scala @@ -16,6 +16,7 @@ package impl import java.util.Spliterator import scala.collection.Stepper.EfficientSplit +// import language.experimental.captureChecking // TODO enable /** Abstracts all the generic operations of stepping over an indexable collection */ private[convert] abstract class IndexedStepperBase[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) diff --git a/scala2-library-cc/src/scala/collection/convert/impl/IteratorStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/IteratorStepper.scala index 68b318c04c9c..393e988959eb 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/IteratorStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/IteratorStepper.scala @@ -17,6 +17,7 @@ import java.util.Spliterator import scala.collection.{AnyStepper, DoubleStepper, IntStepper, LongStepper, Stepper} import scala.jdk.{AnyAccumulator, DoubleAccumulator, IntAccumulator, LongAccumulator} +// import language.experimental.captureChecking // TODO enable private[collection] class AnyIteratorStepper[A](_underlying: Iterator[A]) extends IteratorStepperBase[A, AnyStepper[A], AnyIteratorStepper[A]](_underlying) diff --git a/scala2-library-cc/src/scala/collection/convert/impl/NumericRangeStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/NumericRangeStepper.scala index 89e17bbf467c..7c122f901839 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/NumericRangeStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/NumericRangeStepper.scala @@ -15,6 +15,7 @@ package impl import scala.collection.{AnyStepper, IntStepper, LongStepper, Stepper} import scala.collection.immutable.NumericRange +// import language.experimental.captureChecking // TODO enable private[collection] class AnyNumericRangeStepper[A](underlying: NumericRange[A], _i0: Int, _iN: Int) extends IndexedStepperBase[AnyStepper[A], AnyNumericRangeStepper[A]](_i0, _iN) diff --git a/scala2-library-cc/src/scala/collection/convert/impl/RangeStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/RangeStepper.scala index 282ddb4aa2ad..50ab623a014e 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/RangeStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/RangeStepper.scala @@ -14,6 +14,7 @@ package scala.collection.convert package impl import scala.collection.{IntStepper, Stepper} +// import language.experimental.captureChecking // TODO enable /** Implements Stepper on an integer Range. You don't actually need the Range to do this, * so only the relevant parts are included. Because the arguments are protected, they are @@ -27,7 +28,7 @@ with IntStepper { val ans = myNext myNext += myStep i0 += 1 - ans + ans } else Stepper.throwNSEE() protected def semiclone(half: Int): RangeStepper = new RangeStepper(myNext, myStep, i0, half) diff --git a/scala2-library-cc/src/scala/collection/convert/impl/StringStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/StringStepper.scala index 8990f462b4fd..fe127b857c45 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/StringStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/StringStepper.scala @@ -18,6 +18,7 @@ import java.util.Spliterator import scala.collection.Stepper.EfficientSplit import scala.collection.{IntStepper, Stepper} +// import language.experimental.captureChecking // TODO enable /** Implements `Stepper` on a `String` where you step through chars packed into `Int`. */ diff --git a/scala2-library-cc/src/scala/collection/convert/impl/TableStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/TableStepper.scala index cac041a5237b..6329d83bc2a0 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/TableStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/TableStepper.scala @@ -15,6 +15,7 @@ package impl import scala.collection.Stepper.EfficientSplit import scala.collection._ +// import language.experimental.captureChecking // TODO enable private[collection] abstract class TableStepperBase[A, I >: Null <: AnyRef, Sub >: Null, Semi <: Sub with TableStepperBase[A, I, _, _]]( protected var maxLength: Int, protected val table: Array[I], protected var i0: Int, protected val iN: Int diff --git a/scala2-library-cc/src/scala/collection/convert/impl/VectorStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/VectorStepper.scala index 332ec65d85fd..504e0dac63ea 100644 --- a/scala2-library-cc/src/scala/collection/convert/impl/VectorStepper.scala +++ b/scala2-library-cc/src/scala/collection/convert/impl/VectorStepper.scala @@ -14,6 +14,7 @@ package scala.collection.convert package impl import scala.collection._ +// import language.experimental.captureChecking // TODO enable private[convert] abstract class VectorStepperBase[Sub >: Null, Semi <: Sub]( _i0: Int, @@ -91,7 +92,7 @@ with DoubleStepper { index1 = 32 i0 = half ans - } + } } private[collection] class IntVectorStepper(_i0: Int, _iN: Int, _displayN: Int, _trunk: Array[AnyRef]) @@ -109,7 +110,7 @@ with IntStepper { index1 = 32 i0 = half ans - } + } } private[collection] class LongVectorStepper(_i0: Int, _iN: Int, _displayN: Int, _trunk: Array[AnyRef]) @@ -127,5 +128,5 @@ with LongStepper { index1 = 32 i0 = half ans - } + } } diff --git a/scala2-library-cc/src/scala/collection/generic/BitOperations.scala b/scala2-library-cc/src/scala/collection/generic/BitOperations.scala index 4c64dec9dc1f..f76619a004fa 100644 --- a/scala2-library-cc/src/scala/collection/generic/BitOperations.scala +++ b/scala2-library-cc/src/scala/collection/generic/BitOperations.scala @@ -12,6 +12,7 @@ package scala.collection package generic +import language.experimental.captureChecking /** Some bit operations. diff --git a/scala2-library-cc/src/scala/collection/generic/DefaultSerializationProxy.scala b/scala2-library-cc/src/scala/collection/generic/DefaultSerializationProxy.scala index 69b4b3d96e61..e36bb77ebdb8 100644 --- a/scala2-library-cc/src/scala/collection/generic/DefaultSerializationProxy.scala +++ b/scala2-library-cc/src/scala/collection/generic/DefaultSerializationProxy.scala @@ -16,6 +16,7 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.collection.{Factory, Iterable} import scala.collection.mutable.Builder +import language.experimental.captureChecking /** The default serialization proxy for collection implementations. * diff --git a/scala2-library-cc/src/scala/collection/generic/IsIterable.scala b/scala2-library-cc/src/scala/collection/generic/IsIterable.scala index bf2eab6bb2a6..c309299b615b 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsIterable.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsIterable.scala @@ -12,6 +12,7 @@ package scala.collection package generic +import language.experimental.captureChecking /** A trait which can be used to avoid code duplication when defining extension * methods that should be applicable both to existing Scala collections (i.e., diff --git a/scala2-library-cc/src/scala/collection/generic/IsIterableOnce.scala b/scala2-library-cc/src/scala/collection/generic/IsIterableOnce.scala index 7d7293037bd4..2836ca2bb520 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsIterableOnce.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsIterableOnce.scala @@ -13,6 +13,7 @@ package scala package collection package generic +import language.experimental.captureChecking /** Type class witnessing that a collection representation type `Repr` has * elements of type `A` and has a conversion to `IterableOnce[A]`. diff --git a/scala2-library-cc/src/scala/collection/generic/IsMap.scala b/scala2-library-cc/src/scala/collection/generic/IsMap.scala index 19f75cf7bced..ad7254d2dd61 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsMap.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsMap.scala @@ -15,6 +15,7 @@ package generic import IsMap.Tupled import scala.collection.immutable.{IntMap, LongMap} +import language.experimental.captureChecking /** * Type class witnessing that a collection type `Repr` diff --git a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala index 69ea27d087d1..041d74f84d9c 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala @@ -14,6 +14,8 @@ package scala.collection package generic import scala.reflect.ClassTag +import language.experimental.captureChecking +import language.experimental.captureChecking /** Type class witnessing that a collection representation type `Repr` has * elements of type `A` and has a conversion to `SeqOps[A, Iterable, C]`, for @@ -51,11 +53,24 @@ object IsSeq { implicit def seqOpsIsSeq[CC0[X] <: SeqOps[X, Iterable, CC0[X]], A0]: IsSeq[CC0[A0]] { type A = A0; type C = CC0[A0] } = seqOpsIsSeqVal.asInstanceOf[IsSeq[CC0[A0]] { type A = A0; type C = CC0[A0] }] - implicit def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } = - new IsSeq[CC0[A0]] { + /** !!! Under cc, views are not Seqs and can't use SeqOps. + * So this should be renamed to seqViewIsIterable + */ + implicit def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsIterable[CC0[A0]] { type A = A0; type C = View[A0] } = + new IsIterable[CC0[A0]] { type A = A0 type C = View[A] - def apply(coll: CC0[A0]): SeqOps[A0, View, View[A0]] = coll + def apply(coll: CC0[A0]): IterableOps[A0, View, View[A0]] = coll + } + + /** !!! Under cc, views are not Seqs and can't use SeqOps. + * So this should be renamed to stringViewIsIterable + */ + implicit val stringViewIsSeq: IsIterable[StringView] { type A = Char; type C = View[Char] } = + new IsIterable[StringView] { + type A = Char + type C = View[Char] + def apply(coll: StringView): IterableOps[Char, View, View[Char]] = coll } implicit val stringIsSeq: IsSeq[String] { type A = Char; type C = String } = @@ -68,21 +83,14 @@ object IsSeq { def apply(i: Int): Char = s.charAt(i) 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: IterableFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged + protected[this] def fromSpecific(coll: IterableOnce[Char]^): String = coll.iterator.mkString + def iterableFactory: FreeSeqFactory[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 } } - implicit val stringViewIsSeq: IsSeq[StringView] { type A = Char; type C = View[Char] } = - new IsSeq[StringView] { - type A = Char - type C = View[Char] - def apply(coll: StringView): SeqOps[Char, View, View[Char]] = coll - } - implicit def arrayIsSeq[A0 : ClassTag]: IsSeq[Array[A0]] { type A = A0; type C = Array[A0] } = new IsSeq[Array[A0]] { type A = A0 @@ -91,10 +99,10 @@ object IsSeq { new SeqOps[A, mutable.ArraySeq, Array[A]] { def apply(i: Int): A = a(i) def length: Int = a.length - def toIterable: Iterable[A] = mutable.ArraySeq.make(a) + 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: IterableFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged + protected def fromSpecific(coll: IterableOnce[A]^): Array[A] = Array.from(coll) + def iterableFactory: FreeSeqFactory[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 diff --git a/scala2-library-cc/src/scala/collection/generic/Subtractable.scala b/scala2-library-cc/src/scala/collection/generic/Subtractable.scala index 223997f4e972..2c0967dbaf4b 100644 --- a/scala2-library-cc/src/scala/collection/generic/Subtractable.scala +++ b/scala2-library-cc/src/scala/collection/generic/Subtractable.scala @@ -13,6 +13,7 @@ package scala package collection package generic +import language.experimental.captureChecking /** This trait represents collection-like objects that can be reduced * using a '+' operator. It defines variants of `-` and `--` diff --git a/scala2-library-cc/src/scala/collection/generic/package.scala b/scala2-library-cc/src/scala/collection/generic/package.scala index 0c16aa04dc98..0ba67c1bf76e 100644 --- a/scala2-library-cc/src/scala/collection/generic/package.scala +++ b/scala2-library-cc/src/scala/collection/generic/package.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking package object generic { diff --git a/scala2-library-cc/src/scala/collection/immutable/ArraySeq.scala b/scala2-library-cc/src/scala/collection/immutable/ArraySeq.scala index b006db25ce82..e21490571d29 100644 --- a/scala2-library-cc/src/scala/collection/immutable/ArraySeq.scala +++ b/scala2-library-cc/src/scala/collection/immutable/ArraySeq.scala @@ -23,6 +23,7 @@ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime import scala.util.Sorting import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** * An immutable array. @@ -38,7 +39,8 @@ sealed abstract class ArraySeq[+A] with IndexedSeqOps[A, ArraySeq, ArraySeq[A]] with StrictOptimizedSeqOps[A, ArraySeq, ArraySeq[A]] with EvidenceIterableFactoryDefaults[A, ArraySeq, ClassTag] - with Serializable { + with Serializable + with Pure { /** The tag of the element type. This does not have to be equal to the element type of this ArraySeq. A primitive * ArraySeq can be backed by an array of boxed values and a reference ArraySeq can be backed by an array of a supertype @@ -53,6 +55,8 @@ sealed abstract class ArraySeq[+A] * array of a supertype or subtype of the element type. */ def unsafeArray: Array[_] + def unsafeArrayAsAnyArray = unsafeArray.asInstanceOf[Array[Any]] + protected def evidenceIterableFactory: ArraySeq.type = ArraySeq protected def iterableEvidence: ClassTag[A @uncheckedVariance] = elemTag.asInstanceOf[ClassTag[A]] @@ -79,10 +83,10 @@ sealed abstract class ArraySeq[+A] } override def prepended[B >: A](elem: B): ArraySeq[B] = - ArraySeq.unsafeWrapArray(unsafeArray.prepended[Any](elem)).asInstanceOf[ArraySeq[B]] + ArraySeq.unsafeWrapArray(unsafeArrayAsAnyArray.prepended(elem)).asInstanceOf[ArraySeq[B]] override def appended[B >: A](elem: B): ArraySeq[B] = - ArraySeq.unsafeWrapArray(unsafeArray.appended[Any](elem)).asInstanceOf[ArraySeq[B]] + ArraySeq.unsafeWrapArray(unsafeArrayAsAnyArray.appended[Any](elem)).asInstanceOf[ArraySeq[B]] /** Fast concatenation of two [[ArraySeq]]s. * @@ -124,7 +128,7 @@ sealed abstract class ArraySeq[+A] } } - override def appendedAll[B >: A](suffix: collection.IterableOnce[B]): ArraySeq[B] = { + override def appendedAll[B >: A](suffix: collection.IterableOnce[B]^): ArraySeq[B] = { def genericResult = { val k = suffix.knownSize if (k == 0) this @@ -147,7 +151,7 @@ sealed abstract class ArraySeq[+A] } } - override def prependedAll[B >: A](prefix: collection.IterableOnce[B]): ArraySeq[B] = { + override def prependedAll[B >: A](prefix: collection.IterableOnce[B]^): ArraySeq[B] = { def genericResult = { val k = prefix.knownSize if (k == 0) this @@ -171,7 +175,7 @@ sealed abstract class ArraySeq[+A] } } - override def zip[B](that: collection.IterableOnce[B]): ArraySeq[(A, B)] = + override def zip[B](that: collection.IterableOnce[B]^): ArraySeq[(A, B)] = that match { case bs: ArraySeq[B] => ArraySeq.tabulate(length min bs.length) { i => @@ -181,35 +185,37 @@ sealed abstract class ArraySeq[+A] strictOptimizedZip[B, ArraySeq[(A, B)]](that, iterableFactory.newBuilder) } + private inline def ops[A](xs: Array[A]): ArrayOps[A] = new ArrayOps[A](xs) + override def take(n: Int): ArraySeq[A] = if (unsafeArray.length <= n) this else - ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).take(n)).asInstanceOf[ArraySeq[A]] + ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).take(n)).asInstanceOf[ArraySeq[A]] override def takeRight(n: Int): ArraySeq[A] = if (unsafeArray.length <= n) this else - ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).takeRight(n)).asInstanceOf[ArraySeq[A]] + ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).takeRight(n)).asInstanceOf[ArraySeq[A]] override def drop(n: Int): ArraySeq[A] = if (n <= 0) this else - ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).drop(n)).asInstanceOf[ArraySeq[A]] + ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).drop(n)).asInstanceOf[ArraySeq[A]] override def dropRight(n: Int): ArraySeq[A] = if (n <= 0) this else - ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).dropRight(n)).asInstanceOf[ArraySeq[A]] + ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).dropRight(n)).asInstanceOf[ArraySeq[A]] override def slice(from: Int, until: Int): ArraySeq[A] = if (from <= 0 && unsafeArray.length <= until) this else - ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).slice(from, until)).asInstanceOf[ArraySeq[A]] + ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).slice(from, until)).asInstanceOf[ArraySeq[A]] override def foldLeft[B](z: B)(f: (B, A) => B): B = { // For ArraySeqs with sizes of [100, 1000, 10000] this is [1.3, 1.8, 1.8]x as fast @@ -239,9 +245,9 @@ sealed abstract class ArraySeq[+A] b } - override def tail: ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).tail).asInstanceOf[ArraySeq[A]] + override def tail: ArraySeq[A] = ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).tail).asInstanceOf[ArraySeq[A]] - override def reverse: ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).reverse).asInstanceOf[ArraySeq[A]] + override def reverse: ArraySeq[A] = ArraySeq.unsafeWrapArray(ops(unsafeArrayAsAnyArray).reverse).asInstanceOf[ArraySeq[A]] override protected[this] def className = "ArraySeq" @@ -277,7 +283,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => def empty[A : ClassTag]: ArraySeq[A] = emptyImpl - def from[A](it: scala.collection.IterableOnce[A])(implicit tag: ClassTag[A]): ArraySeq[A] = it match { + def from[A](it: scala.collection.IterableOnce[A]^)(implicit tag: ClassTag[A]): ArraySeq[A] = it match { case as: ArraySeq[A] => as case _ => unsafeWrapArray(Array.from[A](it)) } @@ -325,7 +331,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofRef[T <: AnyRef](val unsafeArray: Array[T]) extends ArraySeq[T] { - def elemTag: ClassTag[T] = ClassTag[T](unsafeArray.getClass.getComponentType) + def elemTag = ClassTag[T](unsafeArray.getClass.getComponentType) def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): T = unsafeArray(i) @@ -355,8 +361,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofByte(val unsafeArray: Array[Byte]) extends ArraySeq[Byte] { - // Type erases to `ManifestFactory.ByteManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Byte.type = ClassTag.Byte + protected def elemTag = ClassTag.Byte def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Byte = unsafeArray(i) @@ -397,8 +402,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofShort(val unsafeArray: Array[Short]) extends ArraySeq[Short] { - // Type erases to `ManifestFactory.ShortManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Short.type = ClassTag.Short + protected def elemTag = ClassTag.Short def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Short = unsafeArray(i) @@ -439,8 +443,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofChar(val unsafeArray: Array[Char]) extends ArraySeq[Char] { - // Type erases to `ManifestFactory.CharManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Char.type = ClassTag.Char + protected def elemTag = ClassTag.Char def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Char = unsafeArray(i) @@ -484,8 +487,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofInt(val unsafeArray: Array[Int]) extends ArraySeq[Int] { - // Type erases to `ManifestFactory.IntManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Int.type = ClassTag.Int + protected def elemTag = ClassTag.Int def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Int = unsafeArray(i) @@ -526,8 +528,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofLong(val unsafeArray: Array[Long]) extends ArraySeq[Long] { - // Type erases to `ManifestFactory.LongManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Long.type = ClassTag.Long + protected def elemTag = ClassTag.Long def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Long = unsafeArray(i) @@ -568,8 +569,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofFloat(val unsafeArray: Array[Float]) extends ArraySeq[Float] { - // Type erases to `ManifestFactory.FloatManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Float.type = ClassTag.Float + protected def elemTag = ClassTag.Float def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Float = unsafeArray(i) @@ -603,8 +603,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofDouble(val unsafeArray: Array[Double]) extends ArraySeq[Double] { - // Type erases to `ManifestFactory.DoubleManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Double.type = ClassTag.Double + protected def elemTag = ClassTag.Double def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Double = unsafeArray(i) @@ -638,8 +637,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofBoolean(val unsafeArray: Array[Boolean]) extends ArraySeq[Boolean] { - // Type erases to `ManifestFactory.BooleanManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Boolean.type = ClassTag.Boolean + protected def elemTag = ClassTag.Boolean def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Boolean = unsafeArray(i) @@ -677,8 +675,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofUnit(val unsafeArray: Array[Unit]) extends ArraySeq[Unit] { - // Type erases to `ManifestFactory.UnitManifest`, but can't annotate that because it's not accessible - protected def elemTag: ClassTag.Unit.type = ClassTag.Unit + protected def elemTag = ClassTag.Unit def length: Int = unsafeArray.length @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): Unit = unsafeArray(i) diff --git a/scala2-library-cc/src/scala/collection/immutable/BitSet.scala b/scala2-library-cc/src/scala/collection/immutable/BitSet.scala index 1b15b029ed91..9c2bfdad54d0 100644 --- a/scala2-library-cc/src/scala/collection/immutable/BitSet.scala +++ b/scala2-library-cc/src/scala/collection/immutable/BitSet.scala @@ -17,6 +17,7 @@ package immutable import BitSetOps.{LogWL, updateArray} import mutable.Builder import scala.annotation.{implicitNotFound, nowarn} +import language.experimental.captureChecking /** A class for immutable bitsets. * $bitsetinfo @@ -37,11 +38,11 @@ sealed abstract class BitSet override def unsorted: Set[Int] = this - override protected def fromSpecific(coll: IterableOnce[Int]): BitSet = bitSetFactory.fromSpecific(coll) + override protected def fromSpecific(coll: IterableOnce[Int]^): BitSet = bitSetFactory.fromSpecific(coll) override protected def newSpecificBuilder: Builder[Int, BitSet] = bitSetFactory.newBuilder override def empty: BitSet = bitSetFactory.empty - def bitSetFactory: BitSet.type = BitSet + def bitSetFactory = BitSet protected[collection] def fromBitMaskNoCopy(elems: Array[Long]): BitSet = BitSet.fromBitMaskNoCopy(elems) @@ -94,7 +95,7 @@ sealed abstract class BitSet @SerialVersionUID(3L) object BitSet extends SpecificIterableFactory[Int, BitSet] { - def fromSpecific(it: scala.collection.IterableOnce[Int]): BitSet = + def fromSpecific(it: scala.collection.IterableOnce[Int]^): BitSet = it match { case bs: BitSet => bs case _ => (newBuilder ++= it).result() diff --git a/scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala b/scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala index 2f6e8e7d45df..3da269dccbd8 100644 --- a/scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala +++ b/scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala @@ -12,10 +12,11 @@ package scala.collection.immutable -import scala.collection.AbstractIterator + import java.lang.Integer.bitCount import java.lang.Math.ceil import java.lang.System.arraycopy +import language.experimental.captureChecking private[collection] object Node { final val HashCodeLength = 32 @@ -104,7 +105,7 @@ private[collection] abstract class Node[T <: Node[T]] { * * @tparam T the trie node type we are iterating over */ -private[immutable] abstract class ChampBaseIterator[A, T <: Node[T]] extends AbstractIterator[A] { +private[immutable] abstract class ChampBaseIterator[T <: Node[T]] { import Node.MaxDepth @@ -112,7 +113,6 @@ private[immutable] abstract class ChampBaseIterator[A, T <: Node[T]] extends Abs // ChampBaseReverseIterator and in convert.impl.ChampStepperBase. // If you change this code, check those also in case they also // need to be modified. - protected var currentValueCursor: Int = 0 protected var currentValueLength: Int = 0 protected var currentValueNode: T = _ @@ -192,7 +192,7 @@ private[immutable] abstract class ChampBaseIterator[A, T <: Node[T]] extends Abs * * @tparam T the trie node type we are iterating over */ -private[immutable] abstract class ChampBaseReverseIterator[A, T <: Node[T]] extends AbstractIterator[A] { +private[immutable] abstract class ChampBaseReverseIterator[T <: Node[T]] { import Node.MaxDepth diff --git a/scala2-library-cc/src/scala/collection/immutable/HashMap.scala b/scala2-library-cc/src/scala/collection/immutable/HashMap.scala index d84da09a1121..8faa37625d51 100644 --- a/scala2-library-cc/src/scala/collection/immutable/HashMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/HashMap.scala @@ -25,6 +25,7 @@ import scala.collection.{Iterator, MapFactory, MapFactoryDefaults, Stepper, Step import scala.runtime.AbstractFunction2 import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** This class implements immutable maps using a Compressed Hash-Array Mapped Prefix-tree. * See paper https://michael.steindorfer.name/publications/oopsla15.pdf for more details. @@ -57,7 +58,7 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode: override def keySet: Set[K] = if (size == 0) Set.empty else new HashKeySet - private[immutable] final class HashKeySet extends ImmutableKeySet { + private final class HashKeySet extends ImmutableKeySet { private[this] def newKeySetOrThis(newHashMap: HashMap[K, _]): Set[K] = if (newHashMap eq HashMap.this) this else newHashMap.keySet @@ -161,7 +162,7 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode: newHashMapOrThis(rootNode.removed(key, keyUnimprovedHash, improve(keyUnimprovedHash), 0)) } - override def concat[V1 >: V](that: scala.IterableOnce[(K, V1)]): HashMap[K, V1] = that match { + override def concat[V1 >: V](that: scala.IterableOnce[(K, V1)]^): HashMap[K, V1] = that match { case hm: HashMap[K, V1] => if (isEmpty) hm else { @@ -384,7 +385,7 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode: else new HashMap(newRootNode) } - override def removedAll(keys: IterableOnce[K]): HashMap[K, V] = { + override def removedAll(keys: IterableOnce[K]^): HashMap[K, V] = { if (isEmpty) { this } else { @@ -698,12 +699,12 @@ private final class BitmapIndexedMapNode[K, +V]( if ((dataMap & bitpos) != 0) { val index = indexFrom(dataMap, mask, bitpos) val payload = getPayload(index) - if (key == payload._1) payload else Iterator.empty.next() + if (key == payload._1) payload else throw new NoSuchElementException } else if ((nodeMap & bitpos) != 0) { val index = indexFrom(nodeMap, mask, bitpos) getNode(index).getTuple(key, originalHash, hash, shift + BitPartitionSize) } else { - Iterator.empty.next() + throw new NoSuchElementException } } @@ -1766,7 +1767,7 @@ private final class BitmapIndexedMapNode[K, +V]( } else { mapOfNewNodes |= bitpos if (newNodes eq null) { - newNodes = mutable.Queue.empty + newNodes = mutable.Queue.empty[MapNode[K, V]] } newNodes += newSubNode } @@ -1872,7 +1873,7 @@ private final class HashCollisionMapNode[K, +V ]( def size: Int = content.length - def apply(key: K, originalHash: Int, hash: Int, shift: Int): V = get(key, originalHash, hash, shift).getOrElse(Iterator.empty.next()) + def apply(key: K, originalHash: Int, hash: Int, shift: Int): V = get(key, originalHash, hash, shift).getOrElse(throw new NoSuchElementException) def get(key: K, originalHash: Int, hash: Int, shift: Int): Option[V] = if (this.hash == hash) { @@ -1882,7 +1883,7 @@ private final class HashCollisionMapNode[K, +V ]( override def getTuple(key: K, originalHash: Int, hash: Int, shift: Int): (K, V) = { val index = indexOf(key) - if (index >= 0) content(index) else Iterator.empty.next() + if (index >= 0) content(index) else throw new NoSuchElementException } def getOrElse[V1 >: V](key: K, originalHash: Int, hash: Int, shift: Int, f: => V1): V1 = { @@ -2095,10 +2096,11 @@ private final class HashCollisionMapNode[K, +V ]( } private final class MapKeyIterator[K, V](rootNode: MapNode[K, V]) - extends ChampBaseIterator[K, MapNode[K, V]](rootNode) { + extends ChampBaseIterator[MapNode[K, V]](rootNode) with Iterator[K] { def next() = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException val key = currentValueNode.getKey(currentValueCursor) currentValueCursor += 1 @@ -2109,10 +2111,11 @@ private final class MapKeyIterator[K, V](rootNode: MapNode[K, V]) } private final class MapValueIterator[K, V](rootNode: MapNode[K, V]) - extends ChampBaseIterator[V, MapNode[K, V]](rootNode) { + extends ChampBaseIterator[MapNode[K, V]](rootNode) with Iterator[V] { def next() = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException val value = currentValueNode.getValue(currentValueCursor) currentValueCursor += 1 @@ -2122,10 +2125,11 @@ private final class MapValueIterator[K, V](rootNode: MapNode[K, V]) } private final class MapKeyValueTupleIterator[K, V](rootNode: MapNode[K, V]) - extends ChampBaseIterator[(K, V), MapNode[K, V]](rootNode) { + extends ChampBaseIterator[MapNode[K, V]](rootNode) with Iterator[(K, V)] { def next() = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException val payload = currentValueNode.getPayload(currentValueCursor) currentValueCursor += 1 @@ -2136,10 +2140,11 @@ private final class MapKeyValueTupleIterator[K, V](rootNode: MapNode[K, V]) } private final class MapKeyValueTupleReverseIterator[K, V](rootNode: MapNode[K, V]) - extends ChampBaseReverseIterator[(K, V), MapNode[K, V]](rootNode) { + extends ChampBaseReverseIterator[MapNode[K, V]](rootNode) with Iterator[(K, V)] { def next() = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException val payload = currentValueNode.getPayload(currentValueCursor) currentValueCursor -= 1 @@ -2149,12 +2154,13 @@ private final class MapKeyValueTupleReverseIterator[K, V](rootNode: MapNode[K, V } private final class MapKeyValueTupleHashIterator[K, V](rootNode: MapNode[K, V]) - extends ChampBaseReverseIterator[Any, MapNode[K, V]](rootNode) { + extends ChampBaseReverseIterator[MapNode[K, V]](rootNode) with Iterator[Any] { private[this] var hash = 0 private[this] var value: V = _ override def hashCode(): Int = MurmurHash3.tuple2Hash(hash, value.##, MurmurHash3.productSeed) - def next(): MapKeyValueTupleHashIterator[K, V] = { - if (!hasNext) Iterator.empty.next() + def next() = { + if (!hasNext) + throw new NoSuchElementException hash = currentValueNode.getHash(currentValueCursor) value = currentValueNode.getValue(currentValueCursor) @@ -2164,7 +2170,7 @@ private final class MapKeyValueTupleHashIterator[K, V](rootNode: MapNode[K, V]) } /** Used in HashMap[K, V]#removeAll(HashSet[K]) */ -private final class MapNodeRemoveAllSetNodeIterator[K](rootSetNode: SetNode[K]) extends ChampBaseIterator[K, SetNode[K]](rootSetNode) { +private final class MapNodeRemoveAllSetNodeIterator[K](rootSetNode: SetNode[K]) extends ChampBaseIterator(rootSetNode) { /** Returns the result of immutably removing all keys in `rootSetNode` from `rootMapNode` */ def removeAll[V](rootMapNode: BitmapIndexedMapNode[K, V]): BitmapIndexedMapNode[K, V] = { var curr = rootMapNode @@ -2180,8 +2186,6 @@ private final class MapNodeRemoveAllSetNodeIterator[K](rootSetNode: SetNode[K]) } curr } - - override def next() = Iterator.empty.next() } /** @@ -2199,7 +2203,7 @@ object HashMap extends MapFactory[HashMap] { def empty[K, V]: HashMap[K, V] = EmptyMap.asInstanceOf[HashMap[K, V]] - def from[K, V](source: collection.IterableOnce[(K, V)]): HashMap[K, V] = + def from[K, V](source: collection.IterableOnce[(K, V)]^): HashMap[K, V] = source match { case hs: HashMap[K, V] => hs case _ => (newBuilder[K, V] ++= source).result() @@ -2363,11 +2367,11 @@ private[immutable] final class HashMapBuilder[K, V] extends ReusableBuilder[(K, this } - override def addAll(xs: IterableOnce[(K, V)]): this.type = { + override def addAll(xs: IterableOnce[(K, V)]^): this.type = { ensureUnaliased() xs match { case hm: HashMap[K, V] => - new ChampBaseIterator[(K, V), MapNode[K, V]](hm.rootNode) { + new ChampBaseIterator[MapNode[K, V]](hm.rootNode) { while(hasNext) { val originalHash = currentValueNode.getHash(currentValueCursor) update( @@ -2380,9 +2384,7 @@ private[immutable] final class HashMapBuilder[K, V] extends ReusableBuilder[(K, ) currentValueCursor += 1 } - - override def next() = Iterator.empty.next() - } + }.asInstanceOf // !!! cc gets confused with representation of capture sets in invariant position case hm: collection.mutable.HashMap[K, V] => val iter = hm.nodeIterator while (iter.hasNext) { diff --git a/scala2-library-cc/src/scala/collection/immutable/HashSet.scala b/scala2-library-cc/src/scala/collection/immutable/HashSet.scala index 736414a180c2..9a3676705201 100644 --- a/scala2-library-cc/src/scala/collection/immutable/HashSet.scala +++ b/scala2-library-cc/src/scala/collection/immutable/HashSet.scala @@ -23,6 +23,7 @@ import scala.collection.generic.DefaultSerializable import scala.collection.mutable.ReusableBuilder import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** This class implements immutable sets using a Compressed Hash-Array Mapped Prefix-tree. * See paper https://michael.steindorfer.name/publications/oopsla15.pdf for more details. @@ -1152,7 +1153,7 @@ private final class BitmapIndexedSetNode[A]( } else { mapOfNewNodes |= bitpos if (newNodes eq null) { - newNodes = mutable.Queue.empty + newNodes = mutable.Queue.empty[SetNode[A]] } newNodes += newSubNode } @@ -1160,7 +1161,7 @@ private final class BitmapIndexedSetNode[A]( newDataMap |= bitpos nodeMigrateToDataTargetMap |= bitpos if (nodesToMigrateToData eq null) { - nodesToMigrateToData = mutable.Queue.empty + nodesToMigrateToData = mutable.Queue.empty[SetNode[A]] } nodesToMigrateToData += newSubNode } @@ -1267,7 +1268,7 @@ private final class BitmapIndexedSetNode[A]( } else { mapOfNewNodes |= bitpos if (newNodes eq null) { - newNodes = mutable.Queue.empty + newNodes = mutable.Queue.empty[SetNode[A]] } newNodes += newSubNode } @@ -1275,7 +1276,7 @@ private final class BitmapIndexedSetNode[A]( newDataMap |= bitpos nodeMigrateToDataTargetMap |= bitpos if (nodesToMigrateToData eq null) { - nodesToMigrateToData = mutable.Queue.empty + nodesToMigrateToData = mutable.Queue.empty[SetNode[A]] } nodesToMigrateToData += newSubNode } @@ -1837,7 +1838,7 @@ private final class HashCollisionSetNode[A](val originalHash: Int, val hash: Int override def hashCode(): Int = throw new UnsupportedOperationException("Trie nodes do not support hashing.") - override def copy(): HashCollisionSetNode[A] = new HashCollisionSetNode[A](originalHash, hash, content) + override def copy() = new HashCollisionSetNode[A](originalHash, hash, content) override def concat(that: SetNode[A], shift: Int): SetNode[A] = that match { case hc: HashCollisionSetNode[A] => @@ -1883,10 +1884,11 @@ private final class HashCollisionSetNode[A](val originalHash: Int, val hash: Int } private final class SetIterator[A](rootNode: SetNode[A]) - extends ChampBaseIterator[A, SetNode[A]](rootNode) { + extends ChampBaseIterator[SetNode[A]](rootNode) with Iterator[A] { def next() = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException val payload = currentValueNode.getPayload(currentValueCursor) currentValueCursor += 1 @@ -1897,10 +1899,11 @@ private final class SetIterator[A](rootNode: SetNode[A]) } private final class SetReverseIterator[A](rootNode: SetNode[A]) - extends ChampBaseReverseIterator[A, SetNode[A]](rootNode) { + extends ChampBaseReverseIterator[SetNode[A]](rootNode) with Iterator[A] { def next(): A = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException val payload = currentValueNode.getPayload(currentValueCursor) currentValueCursor -= 1 @@ -1911,12 +1914,13 @@ private final class SetReverseIterator[A](rootNode: SetNode[A]) } private final class SetHashIterator[A](rootNode: SetNode[A]) - extends ChampBaseIterator[AnyRef, SetNode[A]](rootNode) { + extends ChampBaseIterator[SetNode[A]](rootNode) with Iterator[AnyRef] { private[this] var hash = 0 override def hashCode(): Int = hash def next(): AnyRef = { - if (!hasNext) Iterator.empty.next() + if (!hasNext) + throw new NoSuchElementException hash = currentValueNode.getHash(currentValueCursor) currentValueCursor += 1 @@ -1941,7 +1945,7 @@ object HashSet extends IterableFactory[HashSet] { def empty[A]: HashSet[A] = EmptySet.asInstanceOf[HashSet[A]] - def from[A](source: collection.IterableOnce[A]): HashSet[A] = + def from[A](source: collection.IterableOnce[A]^): HashSet[A] = source match { case hs: HashSet[A] => hs case _ if source.knownSize == 0 => empty[A] @@ -2081,11 +2085,11 @@ private[collection] final class HashSetBuilder[A] extends ReusableBuilder[A, Has this } - override def addAll(xs: IterableOnce[A]) = { + override def addAll(xs: IterableOnce[A]^) = { ensureUnaliased() xs match { case hm: HashSet[A] => - new ChampBaseIterator[A, SetNode[A]](hm.rootNode) { + new ChampBaseIterator[SetNode[A]](hm.rootNode) { while(hasNext) { val originalHash = currentValueNode.getHash(currentValueCursor) update( @@ -2097,8 +2101,7 @@ private[collection] final class HashSetBuilder[A] extends ReusableBuilder[A, Has ) currentValueCursor += 1 } - override def next() = Iterator.empty.next() - } + }.asInstanceOf // !!! cc gets confused with representation of capture sets in invariant position case other => val it = other.iterator while(it.hasNext) addOne(it.next()) diff --git a/scala2-library-cc/src/scala/collection/immutable/IntMap.scala b/scala2-library-cc/src/scala/collection/immutable/IntMap.scala index 240821b11460..88148691e5c0 100644 --- a/scala2-library-cc/src/scala/collection/immutable/IntMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/IntMap.scala @@ -18,6 +18,7 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance import scala.language.implicitConversions +import language.experimental.captureChecking /** Utility class for integer maps. */ @@ -52,7 +53,7 @@ object IntMap { def apply[T](elems: (Int, T)*): IntMap[T] = elems.foldLeft(empty[T])((x, y) => x.updated(y._1, y._2)) - def from[V](coll: IterableOnce[(Int, V)]): IntMap[V] = + def from[V](coll: IterableOnce[(Int, V)]^): IntMap[V] = newBuilder[V].addAll(coll).result() private[immutable] case object Nil extends IntMap[Nothing] { @@ -89,13 +90,13 @@ object IntMap { @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(Int, AnyRef), IntMap[AnyRef]] with Serializable { - def fromSpecific(it: IterableOnce[(Int, AnyRef)]): IntMap[AnyRef] = IntMap.from[AnyRef](it) + def fromSpecific(it: IterableOnce[(Int, AnyRef)]^): IntMap[AnyRef] = IntMap.from[AnyRef](it) def newBuilder: Builder[(Int, AnyRef), IntMap[AnyRef]] = IntMap.newBuilder[AnyRef] } implicit def toBuildFrom[V](factory: IntMap.type): BuildFrom[Any, (Int, V), IntMap[V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (Int, V), IntMap[V]]] private[this] object ToBuildFrom extends BuildFrom[Any, (Int, AnyRef), IntMap[AnyRef]] { - def fromSpecific(from: Any)(it: IterableOnce[(Int, AnyRef)]) = IntMap.from(it) + def fromSpecific(from: Any)(it: IterableOnce[(Int, AnyRef)]^) = IntMap.from(it) def newBuilder(from: Any) = IntMap.newBuilder[AnyRef] } @@ -180,9 +181,9 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] with StrictOptimizedMapOps[Int, T, Map, IntMap[T]] with Serializable { - override protected def fromSpecific(coll: scala.collection.IterableOnce[(Int, T) @uncheckedVariance]): IntMap[T] = + override protected def fromSpecific(coll: scala.collection.IterableOnce[(Int, T) @uncheckedVariance]^): IntMap[T] = intMapFrom[T](coll) - protected def intMapFrom[V2](coll: scala.collection.IterableOnce[(Int, V2)]): IntMap[V2] = { + protected def intMapFrom[V2](coll: scala.collection.IterableOnce[(Int, V2)]^): IntMap[V2] = { val b = IntMap.newBuilder[V2] b.sizeHint(coll) b.addAll(coll) @@ -327,10 +328,10 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] def flatMap[V2](f: ((Int, T)) => IterableOnce[(Int, V2)]): IntMap[V2] = intMapFrom(new View.FlatMap(this, f)) - override def concat[V1 >: T](that: collection.IterableOnce[(Int, V1)]): IntMap[V1] = + override def concat[V1 >: T](that: collection.IterableOnce[(Int, V1)]^): IntMap[V1] = super.concat(that).asInstanceOf[IntMap[V1]] // Already has correct type but not declared as such - override def ++ [V1 >: T](that: collection.IterableOnce[(Int, V1)]): IntMap[V1] = concat(that) + override def ++ [V1 >: T](that: collection.IterableOnce[(Int, V1)]^): IntMap[V1] = concat(that) def collect[V2](pf: PartialFunction[(Int, T), (Int, V2)]): IntMap[V2] = strictOptimizedCollect(IntMap.newBuilder[V2], pf) diff --git a/scala2-library-cc/src/scala/collection/immutable/Iterable.scala b/scala2-library-cc/src/scala/collection/immutable/Iterable.scala index d4199ab3ab14..c4f9900eea8b 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Iterable.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Iterable.scala @@ -13,6 +13,7 @@ package scala.collection.immutable import scala.collection.{IterableFactory, IterableFactoryDefaults} +import language.experimental.captureChecking /** A trait for collections that are guaranteed immutable. * @@ -24,13 +25,14 @@ import scala.collection.{IterableFactory, IterableFactoryDefaults} trait Iterable[+A] extends collection.Iterable[A] with collection.IterableOps[A, Iterable, Iterable[A]] with IterableFactoryDefaults[A, Iterable] { + this: Iterable[A]^ => override def iterableFactory: IterableFactory[Iterable] = Iterable } @SerialVersionUID(3L) object Iterable extends IterableFactory.Delegate[Iterable](List) { - override def from[E](it: IterableOnce[E]): Iterable[E] = it match { + override def from[E](it: IterableOnce[E]^): Iterable[E]^{it} = it match { case iterable: Iterable[E] => iterable case _ => super.from(it) } diff --git a/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala b/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala new file mode 100644 index 000000000000..959dfbe36679 --- /dev/null +++ b/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala @@ -0,0 +1,1378 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package immutable + +import java.io.{ObjectInputStream, ObjectOutputStream} +import java.lang.{StringBuilder => JStringBuilder} + +import scala.annotation.tailrec +import scala.collection.generic.SerializeEnd +import scala.collection.mutable.{Builder, ReusableBuilder, StringBuilder} +import scala.language.implicitConversions +import scala.runtime.Statics +import language.experimental.captureChecking +import annotation.unchecked.uncheckedCaptures + +/** This class implements an immutable linked list. We call it "lazy" + * because it computes its elements only when they are needed. + * + * The class extends Iterable; it is a replacement for LazyList, which + * which implemented Seq. The reason is that under capture checking, we + * assume that all Seqs are strict, and LazyList broke that assumption. + * As a consequence, we declare LazyList is deprecated and unsafe for + * capture checking, and replace it by the current class, LazyListIterable. + * + * Elements are memoized; that is, the value of each element is computed at most once. + * + * Elements are computed in-order and are never skipped. In other words, + * accessing the tail causes the head to be computed first. + * + * How lazy is a `LazyListIterable`? When you have a value of type `LazyListIterable`, you + * don't know yet whether the list is empty or not. If you learn that it is non-empty, + * then you also know that the head has been computed. But the tail is itself + * a `LazyListIterable`, whose emptiness-or-not might remain undetermined. + * + * A `LazyListIterable` may be infinite. For example, `LazyListIterable.from(0)` contains + * all of the natural numbers 0, 1, 2, and so on. For infinite sequences, + * some methods (such as `count`, `sum`, `max` or `min`) will not terminate. + * + * Here is an example: + * + * {{{ + * import scala.math.BigInt + * object Main extends App { + * val fibs: LazyListIterable[BigInt] = + * BigInt(0) #:: BigInt(1) #:: fibs.zip(fibs.tail).map{ n => n._1 + n._2 } + * fibs.take(5).foreach(println) + * } + * + * // prints + * // + * // 0 + * // 1 + * // 1 + * // 2 + * // 3 + * }}} + * + * To illustrate, let's add some output to the definition `fibs`, so we + * see what's going on. + * + * {{{ + * import scala.math.BigInt + * object Main extends App { + * val fibs: LazyListIterable[BigInt] = + * BigInt(0) #:: BigInt(1) #:: + * fibs.zip(fibs.tail).map{ n => + * println(s"Adding \${n._1} and \${n._2}") + * n._1 + n._2 + * } + * fibs.take(5).foreach(println) + * fibs.take(6).foreach(println) + * } + * + * // prints + * // + * // 0 + * // 1 + * // Adding 0 and 1 + * // 1 + * // Adding 1 and 1 + * // 2 + * // Adding 1 and 2 + * // 3 + * + * // And then prints + * // + * // 0 + * // 1 + * // 1 + * // 2 + * // 3 + * // Adding 2 and 3 + * // 5 + * }}} + * + * Note that the definition of `fibs` uses `val` not `def`. The memoization of the + * `LazyListIterable` requires us to have somewhere to store the information and a `val` + * allows us to do that. + * + * Further remarks about the semantics of `LazyListIterable`: + * + * - Though the `LazyListIterable` changes as it is accessed, this does not + * contradict its immutability. Once the values are memoized they do + * not change. Values that have yet to be memoized still "exist", they + * simply haven't been computed yet. + * + * - One must be cautious of memoization; it can eat up memory if you're not + * careful. That's because memoization of the `LazyListIterable` creates a structure much like + * [[scala.collection.immutable.List]]. As long as something is holding on to + * the head, the head holds on to the tail, and so on recursively. + * If, on the other hand, there is nothing holding on to the head (e.g. if we used + * `def` to define the `LazyListIterable`) then once it is no longer being used directly, + * it disappears. + * + * - Note that some operations, including [[drop]], [[dropWhile]], + * [[flatMap]] or [[collect]] may process a large number of intermediate + * elements before returning. + * + * Here's another example. Let's start with the natural numbers and iterate + * over them. + * + * {{{ + * // We'll start with a silly iteration + * def loop(s: String, i: Int, iter: Iterator[Int]): Unit = { + * // Stop after 200,000 + * if (i < 200001) { + * if (i % 50000 == 0) println(s + i) + * loop(s, iter.next(), iter) + * } + * } + * + * // Our first LazyListIterable definition will be a val definition + * val lazylist1: LazyListIterable[Int] = { + * def loop(v: Int): LazyListIterable[Int] = v #:: loop(v + 1) + * loop(0) + * } + * + * // Because lazylist1 is a val, everything that the iterator produces is held + * // by virtue of the fact that the head of the LazyListIterable is held in lazylist1 + * val it1 = lazylist1.iterator + * loop("Iterator1: ", it1.next(), it1) + * + * // We can redefine this LazyListIterable such that all we have is the Iterator left + * // and allow the LazyListIterable to be garbage collected as required. Using a def + * // to provide the LazyListIterable ensures that no val is holding onto the head as + * // is the case with lazylist1 + * def lazylist2: LazyListIterable[Int] = { + * def loop(v: Int): LazyListIterable[Int] = v #:: loop(v + 1) + * loop(0) + * } + * val it2 = lazylist2.iterator + * loop("Iterator2: ", it2.next(), it2) + * + * // And, of course, we don't actually need a LazyListIterable at all for such a simple + * // problem. There's no reason to use a LazyListIterable if you don't actually need + * // one. + * val it3 = new Iterator[Int] { + * var i = -1 + * def hasNext = true + * def next(): Int = { i += 1; i } + * } + * loop("Iterator3: ", it3.next(), it3) + * }}} + * + * - In the `fibs` example earlier, the fact that `tail` works at all is of interest. + * `fibs` has an initial `(0, 1, LazyListIterable(...))`, so `tail` is deterministic. + * If we defined `fibs` such that only `0` were concretely known, then the act + * of determining `tail` would require the evaluation of `tail`, so the + * computation would be unable to progress, as in this code: + * {{{ + * // The first time we try to access the tail we're going to need more + * // information which will require us to recurse, which will require us to + * // recurse, which... + * lazy val sov: LazyListIterable[Vector[Int]] = Vector(0) #:: sov.zip(sov.tail).map { n => n._1 ++ n._2 } + * }}} + * + * The definition of `fibs` above creates a larger number of objects than + * necessary depending on how you might want to implement it. The following + * implementation provides a more "cost effective" implementation due to the + * fact that it has a more direct route to the numbers themselves: + * + * {{{ + * lazy val fib: LazyListIterable[Int] = { + * def loop(h: Int, n: Int): LazyListIterable[Int] = h #:: loop(n, h + n) + * loop(1, 1) + * } + * }}} + * + * The head, the tail and whether the list is empty or not can be initially unknown. + * Once any of those are evaluated, they are all known, though if the tail is + * built with `#::` or `#:::`, it's content still isn't evaluated. Instead, evaluating + * the tails content is deferred until the tails empty status, head or tail is + * evaluated. + * + * Delaying the evaluation of whether a LazyListIterable is empty or not until it's needed + * allows LazyListIterable to not eagerly evaluate any elements on a call to `filter`. + * + * Only when it's further evaluated (which may be never!) any of the elements gets + * forced. + * + * for example: + * + * {{{ + * def tailWithSideEffect: LazyListIterable[Nothing] = { + * println("getting empty LazyListIterable") + * LazyListIterable.empty + * } + * + * val emptyTail = tailWithSideEffect // prints "getting empty LazyListIterable" + * + * val suspended = 1 #:: tailWithSideEffect // doesn't print anything + * val tail = suspended.tail // although the tail is evaluated, *still* nothing is yet printed + * val filtered = tail.filter(_ => false) // still nothing is printed + * filtered.isEmpty // prints "getting empty LazyListIterable" + * }}} + * + * @tparam A the type of the elements contained in this lazy list. + * + * @see [[https://docs.scala-lang.org/overviews/collections-2.13/concrete-immutable-collection-classes.html#lazylists "Scala's Collection Library overview"]] + * section on `LazyLists` for more information. + * @define Coll `LazyListIterable` + * @define coll lazy list + * @define orderDependent + * @define orderDependentFold + * @define appendStackSafety Note: Repeated chaining of calls to append methods (`appended`, + * `appendedAll`, `lazyAppendedAll`) without forcing any of the + * intermediate resulting lazy lists may overflow the stack when + * the final result is forced. + * @define preservesLaziness This method preserves laziness; elements are only evaluated + * individually as needed. + * @define initiallyLazy This method does not evaluate anything until an operation is performed + * on the result (e.g. calling `head` or `tail`, or checking if it is empty). + * @define evaluatesAllElements This method evaluates all elements of the collection. + */ +@SerialVersionUID(3L) +final class LazyListIterable[+A] private(private[this] var lazyState: () => LazyListIterable.State[A]^) + extends AbstractIterable[A] + with Iterable[A] + with IterableOps[A, LazyListIterable, LazyListIterable[A]] + with IterableFactoryDefaults[A, LazyListIterable] + with Serializable { + this: LazyListIterable[A]^ => + import LazyListIterable._ + + @volatile private[this] var stateEvaluated: Boolean = false + @inline private def stateDefined: Boolean = stateEvaluated + private[this] var midEvaluation = false + + private lazy val state: State[A]^ = { + // if it's already mid-evaluation, we're stuck in an infinite + // self-referential loop (also it's empty) + if (midEvaluation) { + throw new RuntimeException("self-referential LazyListIterable or a derivation thereof has no more elements") + } + midEvaluation = true + val res = try lazyState() finally midEvaluation = false + // if we set it to `true` before evaluating, we may infinite loop + // if something expects `state` to already be evaluated + stateEvaluated = true + lazyState = null // allow GC + res + } + + override def iterableFactory: IterableFactory[LazyListIterable] = LazyListIterable + + override def isEmpty: Boolean = state eq State.Empty + + /** @inheritdoc + * + * $preservesLaziness + */ + override def knownSize: Int = if (knownIsEmpty) 0 else -1 + + override def head: A = state.head + + override def tail: LazyListIterable[A]^{this} = state.tail + + @inline private[this] def knownIsEmpty: Boolean = stateEvaluated && (isEmpty: @inline) + @inline private def knownNonEmpty: Boolean = stateEvaluated && !(isEmpty: @inline) + + /** Evaluates all undefined elements of the lazy list. + * + * This method detects cycles in lazy lists, and terminates after all + * elements of the cycle are evaluated. For example: + * + * {{{ + * val ring: LazyListIterable[Int] = 1 #:: 2 #:: 3 #:: ring + * ring.force + * ring.toString + * + * // prints + * // + * // LazyListIterable(1, 2, 3, ...) + * }}} + * + * This method will *not* terminate for non-cyclic infinite-sized collections. + * + * @return this + */ + def force: this.type = { + // Use standard 2x 1x iterator trick for cycle detection ("those" is slow one) + var these, those: LazyListIterable[A]^{this} = this + if (!these.isEmpty) { + these = these.tail + } + while (those ne these) { + if (these.isEmpty) return this + these = these.tail + if (these.isEmpty) return this + these = these.tail + if (these eq those) return this + those = those.tail + } + this + } + + /** @inheritdoc + * + * The iterator returned by this method preserves laziness; elements are + * only evaluated individually as needed. + */ + override def iterator: Iterator[A]^{this} = + if (knownIsEmpty) Iterator.empty + else new LazyIterator(this) + + /** Apply the given function `f` to each element of this linear sequence + * (while respecting the order of the elements). + * + * @param f The treatment to apply to each element. + * @note Overridden here as final to trigger tail-call optimization, which + * replaces 'this' with 'tail' at each iteration. This is absolutely + * necessary for allowing the GC to collect the underlying LazyListIterable as elements + * are consumed. + * @note This function will force the realization of the entire LazyListIterable + * unless the `f` throws an exception. + */ + @tailrec + override def foreach[U](f: A => U): Unit = { + if (!isEmpty) { + f(head) + tail.foreach(f) + } + } + + /** LazyListIterable specialization of foldLeft which allows GC to collect along the + * way. + * + * @tparam B The type of value being accumulated. + * @param z The initial value seeded into the function `op`. + * @param op The operation to perform on successive elements of the `LazyListIterable`. + * @return The accumulated value from successive applications of `op`. + */ + @tailrec + override def foldLeft[B](z: B)(op: (B, A) => B): B = + if (isEmpty) z + else tail.foldLeft(op(z, head))(op) + + // State.Empty doesn't use the SerializationProxy + protected[this] def writeReplace(): AnyRef^{this} = + if (knownNonEmpty) new LazyListIterable.SerializationProxy[A](this) else this + + override protected[this] def className = "LazyListIterable" + + /** The lazy list resulting from the concatenation of this lazy list with the argument lazy list. + * + * $preservesLaziness + * + * $appendStackSafety + * + * @param suffix The collection that gets appended to this lazy list + * @return The lazy list containing elements of this lazy list and the iterable object. + */ + def lazyAppendedAll[B >: A](suffix: => collection.IterableOnce[B]^): LazyListIterable[B]^{this, suffix} = + newLL { + if (isEmpty) suffix match { + case lazyList: LazyListIterable[B] => lazyList.state // don't recompute the LazyListIterable + case coll if coll.knownSize == 0 => State.Empty + case coll => stateFromIterator(coll.iterator) + } + else sCons(head, tail lazyAppendedAll suffix) + } + + /** @inheritdoc + * + * $preservesLaziness + * + * $appendStackSafety + */ + def appendedAll[B >: A](suffix: IterableOnce[B]^): LazyListIterable[B]^{this, suffix} = + if (knownIsEmpty) LazyListIterable.from(suffix) + else lazyAppendedAll(suffix) + + /** @inheritdoc + * + * $preservesLaziness + * + * $appendStackSafety + */ + def appended[B >: A](elem: B): LazyListIterable[B]^{this} = + if (knownIsEmpty) newLL(sCons(elem, LazyListIterable.empty)) + else lazyAppendedAll(Iterator.single(elem)) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def scanLeft[B](z: B)(op: (B, A) => B): LazyListIterable[B]^{this, op} = + if (knownIsEmpty) newLL(sCons(z, LazyListIterable.empty)) + else newLL(scanLeftState(z)(op)) + + private def scanLeftState[B](z: B)(op: (B, A) => B): State[B]^{this, op} = + sCons( + z, + newLL { + if (isEmpty) State.Empty + else tail.scanLeftState(op(z, head))(op) + } + ) + + /** LazyListIterable specialization of reduceLeft which allows GC to collect + * along the way. + * + * @tparam B The type of value being accumulated. + * @param f The operation to perform on successive elements of the `LazyListIterable`. + * @return The accumulated value from successive applications of `f`. + */ + override def reduceLeft[B >: A](f: (B, A) => B): B = { + if (this.isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") + else { + var reducedRes: B = this.head + var left: LazyListIterable[A]^{this} = this.tail + while (!left.isEmpty) { + reducedRes = f(reducedRes, left.head) + left = left.tail + } + reducedRes + } + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def partition(p: A => Boolean): (LazyListIterable[A]^{this, p}, LazyListIterable[A]^{this, p}) = (filter(p), filterNot(p)) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def partitionMap[A1, A2](f: A => Either[A1, A2]): (LazyListIterable[A1]^{this, f}, LazyListIterable[A2]^{this, f}) = { + val (left, right) = map(f).partition(_.isLeft) + (left.map(_.asInstanceOf[Left[A1, _]].value), right.map(_.asInstanceOf[Right[_, A2]].value)) + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def filter(pred: A => Boolean): LazyListIterable[A]^{this, pred} = + if (knownIsEmpty) LazyListIterable.empty + else LazyListIterable.filterImpl(this, pred, isFlipped = false) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def filterNot(pred: A => Boolean): LazyListIterable[A]^{this, pred} = + if (knownIsEmpty) LazyListIterable.empty + else LazyListIterable.filterImpl(this, pred, isFlipped = true) + + /** A `collection.WithFilter` which allows GC of the head of lazy list during processing. + * + * This method is not particularly useful for a lazy list, as [[filter]] already preserves + * laziness. + * + * The `collection.WithFilter` returned by this method preserves laziness; elements are + * only evaluated individually as needed. + */ + override def withFilter(p: A => Boolean): collection.WithFilter[A, LazyListIterable]^{this, p} = + new LazyListIterable.WithFilter(coll, p) + + /** @inheritdoc + * + * $preservesLaziness + */ + def prepended[B >: A](elem: B): LazyListIterable[B] = newLL(sCons(elem, this)) + + /** @inheritdoc + * + * $preservesLaziness + */ + def prependedAll[B >: A](prefix: collection.IterableOnce[B]^): LazyListIterable[B]^{this, prefix} = + if (knownIsEmpty) LazyListIterable.from(prefix) + else if (prefix.knownSize == 0) this + else newLL(stateFromIteratorConcatSuffix(prefix.iterator)(state)) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def map[B](f: A => B): LazyListIterable[B]^{this, f} = + if (knownIsEmpty) LazyListIterable.empty + else (mapImpl(f): @inline) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def tapEach[U](f: A => U): LazyListIterable[A]^{this, f} = map { a => f(a); a } + + private def mapImpl[B](f: A => B): LazyListIterable[B]^{this, f} = + newLL { + if (isEmpty) State.Empty + else sCons(f(head), tail.mapImpl(f)) + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def collect[B](pf: PartialFunction[A, B]^): LazyListIterable[B]^{this, pf} = + if (knownIsEmpty) LazyListIterable.empty + else LazyListIterable.collectImpl(this, pf) + + /** @inheritdoc + * + * This method does not evaluate any elements further than + * the first element for which the partial function is defined. + */ + @tailrec + override def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = + if (isEmpty) None + else { + val res = pf.applyOrElse(head, LazyListIterable.anyToMarker.asInstanceOf[A => B]) + if (res.asInstanceOf[AnyRef] eq Statics.pfMarker) tail.collectFirst(pf) + else Some(res) + } + + /** @inheritdoc + * + * This method does not evaluate any elements further than + * the first element matching the predicate. + */ + @tailrec + override def find(p: A => Boolean): Option[A] = + if (isEmpty) None + else { + val elem = head + if (p(elem)) Some(elem) + else tail.find(p) + } + + /** @inheritdoc + * + * $preservesLaziness + */ + // optimisations are not for speed, but for functionality + // see tickets #153, #498, #2147, and corresponding tests in run/ (as well as run/stream_flatmap_odds.scala) + override def flatMap[B](f: A => IterableOnce[B]^): LazyListIterable[B]^{this, f} = + if (knownIsEmpty) LazyListIterable.empty + else LazyListIterable.flatMapImpl(this, f) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def flatten[B](implicit asIterable: A -> IterableOnce[B]): LazyListIterable[B]^{this} = flatMap(asIterable) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def zip[B](that: collection.IterableOnce[B]^): LazyListIterable[(A, B)]^{this, that} = + if (this.knownIsEmpty || that.knownSize == 0) LazyListIterable.empty + else newLL(zipState(that.iterator)) + + private def zipState[B](it: Iterator[B]^): State[(A, B)]^{this, it} = + if (this.isEmpty || !it.hasNext) State.Empty + else sCons((head, it.next()), newLL { tail zipState it }) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def zipWithIndex: LazyListIterable[(A, Int)]^{this} = this zip LazyListIterable.from(0) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def zipAll[A1 >: A, B](that: collection.Iterable[B]^, thisElem: A1, thatElem: B): LazyListIterable[(A1, B)]^{this, that} = { + if (this.knownIsEmpty) { + if (that.knownSize == 0) LazyListIterable.empty + else LazyListIterable.continually(thisElem) zip that + } else { + if (that.knownSize == 0) zip(LazyListIterable.continually(thatElem)) + else newLL(zipAllState(that.iterator, thisElem, thatElem)) + } + } + + private def zipAllState[A1 >: A, B](it: Iterator[B]^, thisElem: A1, thatElem: B): State[(A1, B)]^{this, it} = { + if (it.hasNext) { + if (this.isEmpty) sCons((thisElem, it.next()), newLL { LazyListIterable.continually(thisElem) zipState it }) + else sCons((this.head, it.next()), newLL { this.tail.zipAllState(it, thisElem, thatElem) }) + } else { + if (this.isEmpty) State.Empty + else sCons((this.head, thatElem), this.tail zip LazyListIterable.continually(thatElem)) + } + } + + /** @inheritdoc + * + * This method is not particularly useful for a lazy list, as [[zip]] already preserves + * laziness. + * + * The `collection.LazyZip2` returned by this method preserves laziness; elements are + * only evaluated individually as needed. + */ + // just in case it can be meaningfully overridden at some point + override def lazyZip[B](that: collection.Iterable[B]^): LazyZip2[A, B, LazyListIterable.this.type]^{this, that} = + super.lazyZip(that) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def unzip[A1, A2](implicit asPair: A -> (A1, A2)): (LazyListIterable[A1]^{this}, LazyListIterable[A2]^{this}) = + (map(asPair(_)._1), map(asPair(_)._2)) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def unzip3[A1, A2, A3](implicit asTriple: A -> (A1, A2, A3)): (LazyListIterable[A1]^{this}, LazyListIterable[A2]^{this}, LazyListIterable[A3]^{this}) = + (map(asTriple(_)._1), map(asTriple(_)._2), map(asTriple(_)._3)) + + /** @inheritdoc + * + * $initiallyLazy + * Additionally, it preserves laziness for all except the first `n` elements. + */ + override def drop(n: Int): LazyListIterable[A]^{this} = + if (n <= 0) this + else if (knownIsEmpty) LazyListIterable.empty + else LazyListIterable.dropImpl(this, n) + + /** @inheritdoc + * + * $initiallyLazy + * Additionally, it preserves laziness for all elements after the predicate returns `false`. + */ + override def dropWhile(p: A => Boolean): LazyListIterable[A]^{this, p} = + if (knownIsEmpty) LazyListIterable.empty + else LazyListIterable.dropWhileImpl(this, p) + + /** @inheritdoc + * + * $initiallyLazy + */ + override def dropRight(n: Int): LazyListIterable[A]^{this} = { + if (n <= 0) this + else if (knownIsEmpty) LazyListIterable.empty + else newLL { + var scout = this + var remaining = n + // advance scout n elements ahead (or until empty) + while (remaining > 0 && !scout.isEmpty) { + remaining -= 1 + scout = scout.tail + } + dropRightState(scout) + } + } + + private def dropRightState(scout: LazyListIterable[_]^): State[A]^{this, scout} = + if (scout.isEmpty) State.Empty + else sCons(head, newLL(tail.dropRightState(scout.tail))) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def take(n: Int): LazyListIterable[A] = + if (knownIsEmpty) LazyListIterable.empty + else (takeImpl(n): @inline) + + private def takeImpl(n: Int): LazyListIterable[A] = { + if (n <= 0) LazyListIterable.empty + else newLL { + if (isEmpty) State.Empty + else sCons(head, tail.takeImpl(n - 1)) + } + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def takeWhile(p: A => Boolean): LazyListIterable[A]^{this, p} = + if (knownIsEmpty) LazyListIterable.empty + else (takeWhileImpl(p): @inline) + + private def takeWhileImpl(p: A => Boolean): LazyListIterable[A]^{this, p} = + newLL { + if (isEmpty || !p(head)) State.Empty + else sCons(head, tail.takeWhileImpl(p)) + } + + /** @inheritdoc + * + * $initiallyLazy + */ + override def takeRight(n: Int): LazyListIterable[A]^{this} = + if (n <= 0 || knownIsEmpty) LazyListIterable.empty + else LazyListIterable.takeRightImpl(this, n) + + /** @inheritdoc + * + * $initiallyLazy + * Additionally, it preserves laziness for all but the first `from` elements. + */ + override def slice(from: Int, until: Int): LazyListIterable[A]^{this} = take(until).drop(from) + + /** @inheritdoc + * + * $evaluatesAllElements + */ + def reverse: LazyListIterable[A] = reverseOnto(LazyListIterable.empty) + + // need contravariant type B to make the compiler happy - still returns LazyListIterable[A] + @tailrec + private def reverseOnto[B >: A](tl: LazyListIterable[B]): LazyListIterable[B] = + if (isEmpty) tl + else tail.reverseOnto(newLL(sCons(head, tl))) + + @tailrec + private def lengthGt(len: Int): Boolean = + if (len < 0) true + else if (isEmpty) false + else tail.lengthGt(len - 1) + + /** @inheritdoc + * + * The iterator returned by this method mostly preserves laziness; + * a single element ahead of the iterator is evaluated. + */ + override def grouped(size: Int): Iterator[LazyListIterable[A]] = { + require(size > 0, "size must be positive, but was " + size) + slidingImpl(size = size, step = size) + } + + /** @inheritdoc + * + * The iterator returned by this method mostly preserves laziness; + * `size - step max 1` elements ahead of the iterator are evaluated. + */ + override def sliding(size: Int, step: Int): Iterator[LazyListIterable[A]] = { + require(size > 0 && step > 0, s"size=$size and step=$step, but both must be positive") + slidingImpl(size = size, step = step) + } + + @inline private def slidingImpl(size: Int, step: Int): Iterator[LazyListIterable[A]] = + if (knownIsEmpty) Iterator.empty + else new SlidingIterator[A](this, size = size, step = step) + + /** @inheritdoc + * + * $preservesLaziness + */ + def padTo[B >: A](len: Int, elem: B): LazyListIterable[B]^{this} = { + if (len <= 0) this + else newLL { + if (isEmpty) LazyListIterable.fill(len)(elem).state + else sCons(head, tail.padTo(len - 1, elem)) + } + } + + /** @inheritdoc + * + * $preservesLaziness + */ + def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): LazyListIterable[B]^{this, other} = + if (knownIsEmpty) LazyListIterable from other + else patchImpl(from, other, replaced) + + private def patchImpl[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): LazyListIterable[B]^{this, other} = + newLL { + if (from <= 0) stateFromIteratorConcatSuffix(other.iterator)(LazyListIterable.dropImpl(this, replaced).state) + else if (isEmpty) stateFromIterator(other.iterator) + else sCons(head, tail.patchImpl(from - 1, other, replaced)) + } + + /** @inheritdoc + * + * $evaluatesAllElements + */ + // overridden just in case a lazy implementation is developed at some point + override def transpose[B](implicit asIterable: A -> collection.Iterable[B]): LazyListIterable[LazyListIterable[B]]^{this} = super.transpose + + /** @inheritdoc + * + * $preservesLaziness + */ + def updated[B >: A](index: Int, elem: B): LazyListIterable[B]^{this} = + if (index < 0) throw new IndexOutOfBoundsException(s"$index") + else updatedImpl(index, elem, index) + + private def updatedImpl[B >: A](index: Int, elem: B, startIndex: Int): LazyListIterable[B]^{this} = { + newLL { + if (index <= 0) sCons(elem, tail) + else if (tail.isEmpty) throw new IndexOutOfBoundsException(startIndex.toString) + else sCons(head, tail.updatedImpl(index - 1, elem, startIndex)) + } + } + + /** Appends all elements of this $coll to a string builder using start, end, and separator strings. + * The written text begins with the string `start` and ends with the string `end`. + * Inside, the string representations (w.r.t. the method `toString`) + * of all elements of this $coll are separated by the string `sep`. + * + * An undefined state is represented with `"<not computed>"` and cycles are represented with `"<cycle>"`. + * + * $evaluatesAllElements + * + * @param sb the string builder to which elements are appended. + * @param start the starting string. + * @param sep the separator string. + * @param end the ending string. + * @return the string builder `b` to which elements were appended. + */ + override def addString(sb: StringBuilder, start: String, sep: String, end: String): sb.type = { + force + addStringNoForce(sb.underlying, start, sep, end) + sb + } + + private[this] def addStringNoForce(b: JStringBuilder, start: String, sep: String, end: String): JStringBuilder = { + b.append(start) + if (!stateDefined) b.append("") + else if (!isEmpty) { + b.append(head) + var cursor = this + inline def appendCursorElement(): Unit = b.append(sep).append(cursor.head) + var scout = tail + inline def scoutNonEmpty: Boolean = scout.stateDefined && !scout.isEmpty + if ((cursor ne scout) && (!scout.stateDefined || (cursor.state ne scout.state))) { + cursor = scout + if (scoutNonEmpty) { + scout = scout.tail + // Use 2x 1x iterator trick for cycle detection; slow iterator can add strings + while ((cursor ne scout) && scoutNonEmpty && (cursor.state ne scout.state)) { + appendCursorElement() + cursor = cursor.tail + scout = scout.tail + if (scoutNonEmpty) scout = scout.tail + } + } + } + if (!scoutNonEmpty) { // Not a cycle, scout hit an end + while (cursor ne scout) { + appendCursorElement() + cursor = cursor.tail + } + // if cursor (eq scout) has state defined, it is empty; else unknown state + if (!cursor.stateDefined) b.append(sep).append("") + } else { + @inline def same(a: LazyListIterable[A]^, b: LazyListIterable[A]^): Boolean = (a eq b) || (a.state eq b.state) + // Cycle. + // If we have a prefix of length P followed by a cycle of length C, + // the scout will be at position (P%C) in the cycle when the cursor + // enters it at P. They'll then collide when the scout advances another + // C - (P%C) ahead of the cursor. + // If we run the scout P farther, then it will be at the start of + // the cycle: (C - (P%C) + (P%C)) == C == 0. So if another runner + // starts at the beginning of the prefix, they'll collide exactly at + // the start of the loop. + var runner = this + var k = 0 + while (!same(runner, scout)) { + runner = runner.tail + scout = scout.tail + k += 1 + } + // Now runner and scout are at the beginning of the cycle. Advance + // cursor, adding to string, until it hits; then we'll have covered + // everything once. If cursor is already at beginning, we'd better + // advance one first unless runner didn't go anywhere (in which case + // we've already looped once). + if (same(cursor, scout) && (k > 0)) { + appendCursorElement() + cursor = cursor.tail + } + while (!same(cursor, scout)) { + appendCursorElement() + cursor = cursor.tail + } + b.append(sep).append("") + } + } + b.append(end) + } + + /** $preservesLaziness + * + * @return a string representation of this collection. An undefined state is + * represented with `"<not computed>"` and cycles are represented with `"<cycle>"` + * + * Examples: + * + * - `"LazyListIterable(4, <not computed>)"`, a non-empty lazy list ; + * - `"LazyListIterable(1, 2, 3, <not computed>)"`, a lazy list with at least three elements ; + * - `"LazyListIterable(1, 2, 3, <cycle>)"`, an infinite lazy list that contains + * a cycle at the fourth element. + */ + override def toString(): String = addStringNoForce(new JStringBuilder(className), "(", ", ", ")").toString + + /** @inheritdoc + * + * $preservesLaziness + */ + @deprecated("Check .knownSize instead of .hasDefiniteSize for more actionable information (see scaladoc for details)", "2.13.0") + override def hasDefiniteSize: Boolean = { + if (!stateDefined) false + else if (isEmpty) true + else { + // Two-iterator trick (2x & 1x speed) for cycle detection. + var those = this + var these = tail + while (those ne these) { + if (!these.stateDefined) return false + else if (these.isEmpty) return true + these = these.tail + if (!these.stateDefined) return false + else if (these.isEmpty) return true + these = these.tail + if (those eq these) return false + those = those.tail + } + false // Cycle detected + } + } +} + +/** + * $factoryInfo + * @define coll lazy list + * @define Coll `LazyListIterable` + */ +@SerialVersionUID(3L) +object LazyListIterable extends IterableFactory[LazyListIterable] { + // Eagerly evaluate cached empty instance + private[this] val _empty = newLL(State.Empty).force + + private sealed trait State[+A] extends Serializable { + this: State[A]^ => + def head: A + def tail: LazyListIterable[A]^ + } + + private object State { + @SerialVersionUID(3L) + object Empty extends State[Nothing] { + def head: Nothing = throw new NoSuchElementException("head of empty lazy list") + def tail: LazyListIterable[Nothing] = throw new UnsupportedOperationException("tail of empty lazy list") + } + + @SerialVersionUID(3L) + final class Cons[A](val head: A, val tail: LazyListIterable[A]^) extends State[A] + } + + /** Creates a new LazyListIterable. */ + @inline private def newLL[A](state: => State[A]^): LazyListIterable[A]^{state} = new LazyListIterable[A](() => state) + + /** Creates a new State.Cons. */ + @inline private def sCons[A](hd: A, tl: LazyListIterable[A]^): State[A]^{tl} = new State.Cons[A](hd, tl) + + private val anyToMarker: Any => Any = _ => Statics.pfMarker + + /* All of the following `Impl` methods are carefully written so as not to + * leak the beginning of the `LazyListIterable`. They copy the initial `LazyListIterable` (`ll`) into + * `var rest`, which gets closed over as a `scala.runtime.ObjectRef`, thus not permanently + * leaking the head of the `LazyListIterable`. Additionally, the methods are written so that, should + * an exception be thrown by the evaluation of the `LazyListIterable` or any supplied function, they + * can continue their execution where they left off. + */ + + private def filterImpl[A](ll: LazyListIterable[A]^, p: A => Boolean, isFlipped: Boolean): LazyListIterable[A]^{ll, p} = { + // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + newLL { + var elem: A = null.asInstanceOf[A] + var found = false + var rest = restRef // var rest = restRef.elem + while (!found && !rest.isEmpty) { + elem = rest.head + found = p(elem) != isFlipped + rest = rest.tail + restRef = rest // restRef.elem = rest + } + if (found) sCons(elem, filterImpl(rest, p, isFlipped)) else State.Empty + } + } + + private def collectImpl[A, B](ll: LazyListIterable[A]^, pf: PartialFunction[A, B]^): LazyListIterable[B]^{ll, pf} = { + // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + newLL { + val marker = Statics.pfMarker + val toMarker = anyToMarker.asInstanceOf[A => B] // safe because Function1 is erased + + var res: B = marker.asInstanceOf[B] // safe because B is unbounded + var rest = restRef // var rest = restRef.elem + while((res.asInstanceOf[AnyRef] eq marker) && !rest.isEmpty) { + res = pf.applyOrElse(rest.head, toMarker) + rest = rest.tail + restRef = rest // restRef.elem = rest + } + if (res.asInstanceOf[AnyRef] eq marker) State.Empty + else sCons(res, collectImpl(rest, pf)) + } + } + + private def flatMapImpl[A, B](ll: LazyListIterable[A]^, f: A => IterableOnce[B]^): LazyListIterable[B]^{ll, f} = { + // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + newLL { + var it: Iterator[B]^{ll, f} = null + var itHasNext = false + var rest = restRef // var rest = restRef.elem + while (!itHasNext && !rest.isEmpty) { + it = f(rest.head).iterator + itHasNext = it.hasNext + if (!itHasNext) { // wait to advance `rest` because `it.next()` can throw + rest = rest.tail + restRef = rest // restRef.elem = rest + } + } + if (itHasNext) { + val head = it.next() + rest = rest.tail + restRef = rest // restRef.elem = rest + sCons(head, newLL(stateFromIteratorConcatSuffix(it)(flatMapImpl(rest, f).state))) + } else State.Empty + } + } + + private def dropImpl[A](ll: LazyListIterable[A]^, n: Int): LazyListIterable[A]^{ll} = { + // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var iRef = n // val iRef = new IntRef(n) + newLL { + var rest = restRef // var rest = restRef.elem + var i = iRef // var i = iRef.elem + while (i > 0 && !rest.isEmpty) { + rest = rest.tail + restRef = rest // restRef.elem = rest + i -= 1 + iRef = i // iRef.elem = i + } + rest.state + } + } + + private def dropWhileImpl[A](ll: LazyListIterable[A]^, p: A => Boolean): LazyListIterable[A]^{ll, p} = { + // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + newLL { + var rest = restRef // var rest = restRef.elem + while (!rest.isEmpty && p(rest.head)) { + rest = rest.tail + restRef = rest // restRef.elem = rest + } + rest.state + } + } + + private def takeRightImpl[A](ll: LazyListIterable[A]^, n: Int): LazyListIterable[A]^{ll} = { + // DO NOT REFERENCE `ll` ANYWHERE ELSE, OR IT WILL LEAK THE HEAD + var restRef: LazyListIterable[A]^{ll*} = ll // restRef is captured by closure arg to newLL, so A is not recognized as parametric + var scoutRef: LazyListIterable[A]^{ll*} = ll // same situation + var remainingRef = n // val remainingRef = new IntRef(n) + newLL { + var scout = scoutRef // var scout = scoutRef.elem + var remaining = remainingRef // var remaining = remainingRef.elem + // advance `scout` `n` elements ahead (or until empty) + while (remaining > 0 && !scout.isEmpty) { + scout = scout.tail + scoutRef = scout // scoutRef.elem = scout + remaining -= 1 + remainingRef = remaining // remainingRef.elem = remaining + } + var rest = restRef // var rest = restRef.elem + // advance `rest` and `scout` in tandem until `scout` reaches the end + while(!scout.isEmpty) { + scout = scout.tail + scoutRef = scout // scoutRef.elem = scout + rest = rest.tail // can't throw an exception as `scout` has already evaluated its tail + restRef = rest // restRef.elem = rest + } + // `rest` is the last `n` elements (or all of them) + rest.state + } + } + + /** An alternative way of building and matching lazy lists using LazyListIterable.cons(hd, tl). + */ + object cons { + /** A lazy list consisting of a given first element and remaining elements + * @param hd The first element of the result lazy list + * @param tl The remaining elements of the result lazy list + */ + def apply[A](hd: => A, tl: => LazyListIterable[A]^): LazyListIterable[A]^{hd, tl} = newLL(sCons(hd, newLL(tl.state))) + + /** Maps a lazy list to its head and tail */ + def unapply[A](xs: LazyListIterable[A]^): Option[(A, LazyListIterable[A]^{xs})] = #::.unapply(xs) + } + + extension [A](l: => LazyListIterable[A]) + /** Construct a LazyListIterable consisting of a given first element followed by elements + * from another LazyListIterable. + */ + def #:: [B >: A](elem: => B): LazyListIterable[B]^{elem, l} = newLL(sCons(elem, newLL(l.state))) + + /** Construct a LazyListIterable consisting of the concatenation of the given LazyListIterable and + * another LazyListIterable. + */ + def #:::[B >: A](prefix: LazyListIterable[B]^): LazyListIterable[B]^{prefix, l} = prefix lazyAppendedAll l + + object #:: { + def unapply[A](s: LazyListIterable[A]^): Option[(A, LazyListIterable[A]^{s})] = + if (!s.isEmpty) Some((s.head, s.tail)) else None + } + + def from[A](coll: collection.IterableOnce[A]^): LazyListIterable[A]^{coll} = coll match { + case lazyList: LazyListIterable[A] => lazyList + case _ if coll.knownSize == 0 => empty[A] + case _ => newLL(stateFromIterator(coll.iterator)) + } + + def empty[A]: LazyListIterable[A] = _empty + + /** Creates a State from an Iterator, with another State appended after the Iterator + * is empty. + */ + private def stateFromIteratorConcatSuffix[A](it: Iterator[A]^)(suffix: => State[A]^): State[A]^{it, suffix} = + if (it.hasNext) sCons(it.next(), newLL(stateFromIteratorConcatSuffix(it)(suffix))) + else suffix + + /** Creates a State from an IterableOnce. */ + private def stateFromIterator[A](it: Iterator[A]^): State[A]^{it} = + if (it.hasNext) sCons(it.next(), newLL(stateFromIterator(it))) + else State.Empty + + override def concat[A](xss: collection.Iterable[A]*): LazyListIterable[A] = + if (xss.knownSize == 0) empty + else newLL(concatIterator(xss.iterator)) + + private def concatIterator[A](it: Iterator[collection.Iterable[A]]^): State[A]^{it} = + if (!it.hasNext) State.Empty + else stateFromIteratorConcatSuffix(it.next().iterator)(concatIterator(it)) + + /** An infinite LazyListIterable that repeatedly applies a given function to a start value. + * + * @param start the start value of the LazyListIterable + * @param f the function that's repeatedly applied + * @return the LazyListIterable returning the infinite sequence of values `start, f(start), f(f(start)), ...` + */ + def iterate[A](start: => A)(f: A => A): LazyListIterable[A]^{start, f} = + newLL { + val head = start + sCons(head, iterate(f(head))(f)) + } + + /** + * Create an infinite LazyListIterable starting at `start` and incrementing by + * step `step`. + * + * @param start the start value of the LazyListIterable + * @param step the increment value of the LazyListIterable + * @return the LazyListIterable starting at value `start`. + */ + def from(start: Int, step: Int): LazyListIterable[Int] = + newLL(sCons(start, from(start + step, step))) + + /** + * Create an infinite LazyListIterable starting at `start` and incrementing by `1`. + * + * @param start the start value of the LazyListIterable + * @return the LazyListIterable starting at value `start`. + */ + def from(start: Int): LazyListIterable[Int] = from(start, 1) + + /** + * Create an infinite LazyListIterable containing the given element expression (which + * is computed for each occurrence). + * + * @param elem the element composing the resulting LazyListIterable + * @return the LazyListIterable containing an infinite number of elem + */ + def continually[A](elem: => A): LazyListIterable[A]^{elem} = newLL(sCons(elem, continually(elem))) + + override def fill[A](n: Int)(elem: => A): LazyListIterable[A]^{elem} = + if (n > 0) newLL(sCons(elem, fill(n - 1)(elem))) else empty + + override def tabulate[A](n: Int)(f: Int => A): LazyListIterable[A]^{f} = { + def at(index: Int): LazyListIterable[A]^{f} = + if (index < n) newLL(sCons(f(index), at(index + 1))) else empty + + at(0) + } + + // significantly simpler than the iterator returned by Iterator.unfold + override def unfold[A, S](init: S)(f: S => Option[(A, S)]): LazyListIterable[A]^{f} = + newLL { + f(init) match { + case Some((elem, state)) => sCons(elem, unfold(state)(f)) + case None => State.Empty + } + } + + /** The builder returned by this method only evaluates elements + * of collections added to it as needed. + * + * @tparam A the type of the ${coll}’s elements + * @return A builder for $Coll objects. + */ + def newBuilder[A]: Builder[A, LazyListIterable[A]] = new LazyBuilder[A] + + private class LazyIterator[+A](private[this] var lazyList: LazyListIterable[A]^) extends AbstractIterator[A] { + override def hasNext: Boolean = !lazyList.isEmpty + + override def next(): A = + if (lazyList.isEmpty) Iterator.empty.next() + else { + val res = lazyList.head + lazyList = lazyList.tail + res + } + } + + private class SlidingIterator[A](private[this] var lazyList: LazyListIterable[A]^, size: Int, step: Int) + extends AbstractIterator[LazyListIterable[A]] { + this: SlidingIterator[A]^ => + private val minLen = size - step max 0 + private var first = true + + def hasNext: Boolean = + if (first) !lazyList.isEmpty + else lazyList.lengthGt(minLen) + + def next(): LazyListIterable[A] = { + if (!hasNext) Iterator.empty.next() + else { + first = false + val list = lazyList + lazyList = list.drop(step) + list.take(size) + } + } + } + + private final class WithFilter[A] private[LazyListIterable](lazyList: LazyListIterable[A]^, p: A => Boolean) + extends collection.WithFilter[A, LazyListIterable] { + this: WithFilter[A]^ => + private[this] val filtered = lazyList.filter(p) + def map[B](f: A => B): LazyListIterable[B]^{this, f} = filtered.map(f) + def flatMap[B](f: A => IterableOnce[B]^): LazyListIterable[B]^{this, f} = filtered.flatMap(f) + def foreach[U](f: A => U): Unit = filtered.foreach(f) + def withFilter(q: A => Boolean): collection.WithFilter[A, LazyListIterable]^{this, q} = new WithFilter(filtered, q) + } + + private final class LazyBuilder[A] extends ReusableBuilder[A, LazyListIterable[A]] { + import LazyBuilder._ + + private[this] var next: DeferredState[A] = _ + private[this] var list: LazyListIterable[A] = _ + + clear() + + override def clear(): Unit = { + val deferred = new DeferredState[A] + list = newLL(deferred.eval()) + next = deferred + } + + override def result(): LazyListIterable[A] = { + next init State.Empty + list + } + + override def addOne(elem: A): this.type = { + val deferred = new DeferredState[A] + next init sCons(elem, newLL(deferred.eval())) + next = deferred + this + } + + // lazy implementation which doesn't evaluate the collection being added + override def addAll(xs: IterableOnce[A]^): this.type = { + if (xs.knownSize != 0) { + val deferred = new DeferredState[A] + next.init(stateFromIteratorConcatSuffix(xs.iterator)(deferred.eval())) + next = deferred + } + this + } + } + + private object LazyBuilder { + final class DeferredState[A] { + this: DeferredState[A]^ => + private[this] var _state: (() => State[A]^) @uncheckedCaptures = _ + + def eval(): State[A]^ = { + val state = _state + if (state == null) throw new IllegalStateException("uninitialized") + state() + } + + // racy + def init(state: => State[A]^): Unit = { + if (_state != null) throw new IllegalStateException("already initialized") + _state = () => state + } + } + } + + /** This serialization proxy is used for LazyLists which start with a sequence of evaluated cons cells. + * The forced sequence is serialized in a compact, sequential format, followed by the unevaluated tail, which uses + * standard Java serialization to store the complete structure of unevaluated thunks. This allows the serialization + * of long evaluated lazy lists without exhausting the stack through recursive serialization of cons cells. + */ + @SerialVersionUID(3L) + final class SerializationProxy[A](_coll: LazyListIterable[A]^) extends Serializable { + + @transient protected var coll: LazyListIterable[A]^{this} = _coll + + private[this] def writeObject(out: ObjectOutputStream): Unit = { + out.defaultWriteObject() + var these = coll + while (these.knownNonEmpty) { + out.writeObject(these.head) + these = these.tail + } + out.writeObject(SerializeEnd) + out.writeObject(these) + } + + private[this] def readObject(in: ObjectInputStream): Unit = { + in.defaultReadObject() + val init = new mutable.ListBuffer[A] + var initRead = false + while (!initRead) in.readObject match { + case SerializeEnd => initRead = true + case a => init += a.asInstanceOf[A] + } + val tail = in.readObject().asInstanceOf[LazyListIterable[A]] + // scala/scala#10118: caution that no code path can evaluate `tail.state` + // before the resulting LazyListIterable is returned + val it = init.toList.iterator + coll = newLL(stateFromIteratorConcatSuffix(it)(tail.state)) + } + + private[this] def readResolve(): Any = coll + } +} diff --git a/scala2-library-cc/src/scala/collection/immutable/List.scala b/scala2-library-cc/src/scala/collection/immutable/List.scala index 5358922752fb..913de8b0be08 100644 --- a/scala2-library-cc/src/scala/collection/immutable/List.scala +++ b/scala2-library-cc/src/scala/collection/immutable/List.scala @@ -19,6 +19,7 @@ import scala.annotation.tailrec import mutable.{Builder, ListBuffer} import scala.collection.generic.DefaultSerializable import scala.runtime.Statics.releaseFence +import language.experimental.captureChecking /** A class for immutable linked lists representing ordered collections * of elements of type `A`. @@ -143,7 +144,7 @@ sealed abstract class List[+A] override def prepended[B >: A](elem: B): List[B] = elem :: this - override def prependedAll[B >: A](prefix: collection.IterableOnce[B]): List[B] = prefix match { + override def prependedAll[B >: A](prefix: collection.IterableOnce[B]^): List[B] = prefix match { case xs: List[B] => xs ::: this case _ if prefix.knownSize == 0 => this case b: ListBuffer[B] if this.isEmpty => b.toList @@ -165,7 +166,7 @@ sealed abstract class List[+A] } // When calling appendAll with another list `suffix`, avoid copying `suffix` - override def appendedAll[B >: A](suffix: collection.IterableOnce[B]): List[B] = suffix match { + override def appendedAll[B >: A](suffix: collection.IterableOnce[B]^): List[B] = suffix match { case xs: List[B] => this ::: xs case _ => super.appendedAll(suffix) } @@ -257,7 +258,7 @@ sealed abstract class List[+A] } } - final override def collect[B](pf: PartialFunction[A, B]): List[B] = { + final override def collect[B](pf: PartialFunction[A, B]^): List[B] = { if (this eq Nil) Nil else { var rest = this var h: ::[B] = null @@ -285,7 +286,7 @@ sealed abstract class List[+A] } } - final override def flatMap[B](f: A => IterableOnce[B]): List[B] = { + final override def flatMap[B](f: A => IterableOnce[B]^): List[B] = { var rest = this var h: ::[B] = null var t: ::[B] = null @@ -666,7 +667,7 @@ case object Nil extends List[Nothing] { override def init: Nothing = throw new UnsupportedOperationException("init of empty list") override def knownSize: Int = 0 override def iterator: Iterator[Nothing] = Iterator.empty - override def unzip[A1, A2](implicit asPair: Nothing => (A1, A2)): (List[A1], List[A2]) = EmptyUnzip + override def unzip[A1, A2](implicit asPair: Nothing -> (A1, A2)): (List[A1], List[A2]) = EmptyUnzip @transient private[this] val EmptyUnzip = (Nil, Nil) @@ -681,9 +682,9 @@ case object Nil extends List[Nothing] { object List extends StrictOptimizedSeqFactory[List] { private val TupleOfNil = (Nil, Nil) - def from[B](coll: collection.IterableOnce[B]): List[B] = Nil.prependedAll(coll) + def from[B](coll: collection.IterableOnce[B]^): List[B] = Nil.prependedAll(coll) - def newBuilder[A]: Builder[A, List[A]] = new ListBuffer() + def newBuilder[A]: Builder[A, List[A]] = new ListBuffer[A]() def empty[A]: List[A] = Nil diff --git a/scala2-library-cc/src/scala/collection/immutable/ListMap.scala b/scala2-library-cc/src/scala/collection/immutable/ListMap.scala index 4a2b8dbd807c..06f9b0e91ec1 100644 --- a/scala2-library-cc/src/scala/collection/immutable/ListMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/ListMap.scala @@ -19,6 +19,7 @@ import scala.collection.mutable.ReusableBuilder import scala.collection.generic.DefaultSerializable import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** * This class implements immutable maps using a list-based data structure. List map iterators and @@ -239,7 +240,7 @@ object ListMap extends MapFactory[ListMap] { private object EmptyListMap extends ListMap[Any, Nothing] - def from[K, V](it: collection.IterableOnce[(K, V)]): ListMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): ListMap[K, V] = it match { case lm: ListMap[K, V] => lm case lhm: collection.mutable.LinkedHashMap[K, V] => @@ -322,7 +323,7 @@ private[immutable] final class ListMapBuilder[K, V] extends mutable.ReusableBuil } this } - override def addAll(xs: IterableOnce[(K, V)]): this.type = { + override def addAll(xs: IterableOnce[(K, V)]^): this.type = { if (isAliased) { super.addAll(xs) } else if (underlying.nonEmpty) { diff --git a/scala2-library-cc/src/scala/collection/immutable/ListSet.scala b/scala2-library-cc/src/scala/collection/immutable/ListSet.scala index e2ab0de858da..ab5e8c65600b 100644 --- a/scala2-library-cc/src/scala/collection/immutable/ListSet.scala +++ b/scala2-library-cc/src/scala/collection/immutable/ListSet.scala @@ -17,6 +17,7 @@ package immutable import mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec import scala.collection.generic.DefaultSerializable +import language.experimental.captureChecking /** * This class implements immutable sets using a list-based data structure. List set iterators and @@ -117,7 +118,7 @@ sealed class ListSet[A] @SerialVersionUID(3L) object ListSet extends IterableFactory[ListSet] { - def from[E](it: scala.collection.IterableOnce[E]): ListSet[E] = + def from[E](it: scala.collection.IterableOnce[E]^): ListSet[E] = it match { case ls: ListSet[E] => ls case _ if it.knownSize == 0 => empty[E] diff --git a/scala2-library-cc/src/scala/collection/immutable/LongMap.scala b/scala2-library-cc/src/scala/collection/immutable/LongMap.scala index c418dc7616ac..1e32cb88767d 100644 --- a/scala2-library-cc/src/scala/collection/immutable/LongMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/LongMap.scala @@ -20,6 +20,7 @@ import scala.collection.mutable.{Builder, ImmutableBuilder, ListBuffer} import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance import scala.language.implicitConversions +import language.experimental.captureChecking /** Utility class for long maps. */ @@ -52,7 +53,7 @@ object LongMap { def apply[T](elems: (Long, T)*): LongMap[T] = elems.foldLeft(empty[T])((x, y) => x.updated(y._1, y._2)) - def from[V](coll: IterableOnce[(Long, V)]): LongMap[V] = + def from[V](coll: IterableOnce[(Long, V)]^): LongMap[V] = newBuilder[V].addAll(coll).result() def newBuilder[V]: Builder[(Long, V), LongMap[V]] = @@ -86,13 +87,13 @@ object LongMap { @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(Long, AnyRef), LongMap[AnyRef]] with Serializable { - def fromSpecific(it: IterableOnce[(Long, AnyRef)]): LongMap[AnyRef] = LongMap.from[AnyRef](it) + def fromSpecific(it: IterableOnce[(Long, AnyRef)]^): LongMap[AnyRef] = LongMap.from[AnyRef](it) def newBuilder: Builder[(Long, AnyRef), LongMap[AnyRef]] = LongMap.newBuilder[AnyRef] } implicit def toBuildFrom[V](factory: LongMap.type): BuildFrom[Any, (Long, V), LongMap[V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (Long, V), LongMap[V]]] private[this] object ToBuildFrom extends BuildFrom[Any, (Long, AnyRef), LongMap[AnyRef]] { - def fromSpecific(from: Any)(it: IterableOnce[(Long, AnyRef)]) = LongMap.from(it) + def fromSpecific(from: Any)(it: IterableOnce[(Long, AnyRef)]^) = LongMap.from(it) def newBuilder(from: Any) = LongMap.newBuilder[AnyRef] } @@ -176,7 +177,7 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] with StrictOptimizedMapOps[Long, T, Map, LongMap[T]] with Serializable { - override protected def fromSpecific(coll: scala.collection.IterableOnce[(Long, T)] @uncheckedVariance): LongMap[T] = { + override protected def fromSpecific(coll: scala.collection.IterableOnce[(Long, T) @uncheckedVariance]^): LongMap[T] = { //TODO should this be the default implementation of this method in StrictOptimizedIterableOps? val b = newSpecificBuilder b.sizeHint(coll) @@ -478,10 +479,10 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] def flatMap[V2](f: ((Long, T)) => IterableOnce[(Long, V2)]): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) - override def concat[V1 >: T](that: scala.collection.IterableOnce[(Long, V1)]): LongMap[V1] = + override def concat[V1 >: T](that: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = super.concat(that).asInstanceOf[LongMap[V1]] // Already has correct type but not declared as such - override def ++ [V1 >: T](that: scala.collection.IterableOnce[(Long, V1)]): LongMap[V1] = concat(that) + override def ++ [V1 >: T](that: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = concat(that) def collect[V2](pf: PartialFunction[(Long, T), (Long, V2)]): LongMap[V2] = strictOptimizedCollect(LongMap.newBuilder[V2], pf) diff --git a/scala2-library-cc/src/scala/collection/immutable/Map.scala b/scala2-library-cc/src/scala/collection/immutable/Map.scala index 5311041f66e8..1b74883bb612 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Map.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Map.scala @@ -18,7 +18,7 @@ import scala.annotation.unchecked.uncheckedVariance import scala.collection.generic.DefaultSerializable import scala.collection.immutable.Map.Map4 import scala.collection.mutable.{Builder, ReusableBuilder} -import SeqMap.{SeqMap1, SeqMap2, SeqMap3, SeqMap4} +import language.experimental.captureChecking /** Base type of immutable Maps */ trait Map[K, +V] @@ -29,7 +29,7 @@ trait Map[K, +V] override def mapFactory: scala.collection.MapFactory[Map] = Map - override final def toMap[K2, V2](implicit ev: (K, V) <:< (K2, V2)): Map[K2, V2] = Map.from(this.asInstanceOf[Map[K2, V2]]) + override final def toMap[K2, V2](implicit ev: (K, V) <:< (K2, V2)): Map[K2, V2] = this.asInstanceOf[Map[K2, V2]] /** The same map with a given default function. * Note: The default is only used for `apply`. Other methods like `get`, `contains`, `iterator`, `keys`, etc. @@ -40,7 +40,7 @@ trait Map[K, +V] * @param d the function mapping keys to values, used for non-present keys * @return a wrapper of the map with a default value */ - def withDefault[V1 >: V](d: K => V1): Map[K, V1] = new Map.WithDefault[K, V1](this, d) + def withDefault[V1 >: V](d: K -> V1): Map[K, V1] = new Map.WithDefault[K, V1](this, d) /** The same map with a given default value. * Note: The default is only used for `apply`. Other methods like `get`, `contains`, `iterator`, `keys`, etc. @@ -87,10 +87,10 @@ trait MapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C] * @return a new $coll that contains all elements of the current $coll * except one less occurrence of each of the elements of `elems`. */ - def removedAll(keys: IterableOnce[K]): C = keys.iterator.foldLeft[C](coll)(_ - _) + def removedAll(keys: IterableOnce[K]^): C = keys.iterator.foldLeft[C](coll)(_ - _) /** Alias for `removedAll` */ - @`inline` final override def -- (keys: IterableOnce[K]): C = removedAll(keys) + @`inline` final override def -- (keys: IterableOnce[K]^): C = removedAll(keys) /** Creates a new map obtained by updating this map with a given key/value pair. * @param key the key @@ -142,7 +142,7 @@ trait MapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C] override def keySet: Set[K] = new ImmutableKeySet /** The implementation class of the set returned by `keySet` */ - protected[immutable] class ImmutableKeySet extends AbstractSet[K] with GenKeySet with DefaultSerializable { + protected class ImmutableKeySet extends AbstractSet[K] with GenKeySet with DefaultSerializable { def incl(elem: K): Set[K] = if (this(elem)) this else empty ++ this + elem def excl(elem: K): Set[K] = if (this(elem)) empty ++ this - elem else this } @@ -154,7 +154,7 @@ trait StrictOptimizedMapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapO with collection.StrictOptimizedMapOps[K, V, CC, C] with StrictOptimizedIterableOps[(K, V), Iterable, C] { - override def concat [V1 >: V](that: collection.IterableOnce[(K, V1)]): CC[K, V1] = { + override def concat [V1 >: V](that: collection.IterableOnce[(K, V1)]^): CC[K, V1] = { var result: CC[K, V1] = coll val it = that.iterator while (it.hasNext) result = result + it.next() @@ -172,7 +172,7 @@ trait StrictOptimizedMapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapO object Map extends MapFactory[Map] { @SerialVersionUID(3L) - class WithDefault[K, +V](val underlying: Map[K, V], val defaultValue: K => V) + class WithDefault[K, +V](val underlying: Map[K, V], val defaultValue: K -> V) extends AbstractMap[K, V] with MapOps[K, V, Map, WithDefault[K, V]] with Serializable { @@ -188,7 +188,7 @@ object Map extends MapFactory[Map] { override def mapFactory: MapFactory[Map] = underlying.mapFactory - override def concat [V2 >: V](xs: collection.IterableOnce[(K, V2)]): WithDefault[K, V2] = + override def concat [V2 >: V](xs: collection.IterableOnce[(K, V2)]^): WithDefault[K, V2] = new WithDefault(underlying.concat(xs), defaultValue) def removed(key: K): WithDefault[K, V] = new WithDefault[K, V](underlying.removed(key), defaultValue) @@ -198,7 +198,7 @@ object Map extends MapFactory[Map] { override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) - override protected def fromSpecific(coll: collection.IterableOnce[(K, V)] @uncheckedVariance): WithDefault[K, V] = + override protected def fromSpecific(coll: collection.IterableOnce[(K, V) @uncheckedVariance]^): WithDefault[K, V] = new WithDefault[K, V](mapFactory.from(coll), defaultValue) override protected def newSpecificBuilder: Builder[(K, V), WithDefault[K, V]] @uncheckedVariance = @@ -207,30 +207,11 @@ object Map extends MapFactory[Map] { def empty[K, V]: Map[K, V] = EmptyMap.asInstanceOf[Map[K, V]] - def from[K, V](it: IterableOnce[(K, V)]): Map[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): Map[K, V] = it match { case it: Iterable[_] if it.isEmpty => empty[K, V] - // Since IterableOnce[(K, V)] launders the variance of K, - // identify only our implementations which can be soundly substituted. - // For example, the ordering used by sorted maps would fail on widened key type. (scala/bug#12745) - // The following type test is not sufficient: case m: Map[K, V] => m - case m: HashMap[K, V] => m - case m: Map1[K, V] => m - case m: Map2[K, V] => m - case m: Map3[K, V] => m - case m: Map4[K, V] => m - //case m: WithDefault[K, V] => m // cf SortedMap.WithDefault - //case m: SeqMap[K, V] => SeqMap.from(it) // inlined here to avoid hard dependency - case m: ListMap[K, V] => m - case m: TreeSeqMap[K, V] => m - case m: VectorMap[K, V] => m - case m: SeqMap1[K, V] => m - case m: SeqMap2[K, V] => m - case m: SeqMap3[K, V] => m - case m: SeqMap4[K, V] => m - - // Maps with a reified key type must be rebuilt, such as `SortedMap` and `IntMap`. - case _ => newBuilder[K, V].addAll(it).result() + case m: Map[K, V] => m + case _ => (newBuilder[K, V] ++= it).result() } def newBuilder[K, V]: Builder[(K, V), Map[K, V]] = new MapBuilderImpl @@ -249,7 +230,7 @@ object Map extends MapFactory[Map] { override def valuesIterator: Iterator[Nothing] = Iterator.empty def updated [V1] (key: Any, value: V1): Map[Any, V1] = new Map1(key, value) def removed(key: Any): Map[Any, Nothing] = this - override def concat[V2 >: Nothing](suffix: IterableOnce[(Any, V2)]): Map[Any, V2] = suffix match { + override def concat[V2 >: Nothing](suffix: IterableOnce[(Any, V2)]^): Map[Any, V2] = suffix match { case m: immutable.Map[Any, V2] => m case _ => super.concat(suffix) } @@ -333,7 +314,7 @@ object Map extends MapFactory[Map] { override protected def nextResult(k: K, v: V): V = v } - private abstract class Map2Iterator[A] extends AbstractIterator[A] { + private abstract class Map2Iterator[A] extends AbstractIterator[A], Pure { private[this] var i = 0 override def hasNext: Boolean = i < 2 override def next(): A = { @@ -436,7 +417,7 @@ object Map extends MapFactory[Map] { override protected def nextResult(k: K, v: V): V = v } - private abstract class Map3Iterator[A] extends AbstractIterator[A] { + private abstract class Map3Iterator[A] extends AbstractIterator[A], Pure { private[this] var i = 0 override def hasNext: Boolean = i < 3 override def next(): A = { @@ -556,7 +537,7 @@ object Map extends MapFactory[Map] { override protected def nextResult(k: K, v: V): V = v } - private abstract class Map4Iterator[A] extends AbstractIterator[A] { + private abstract class Map4Iterator[A] extends AbstractIterator[A], Pure { private[this] var i = 0 override def hasNext: Boolean = i < 4 override def next(): A = { @@ -702,7 +683,7 @@ private[immutable] final class MapBuilderImpl[K, V] extends ReusableBuilder[(K, def addOne(elem: (K, V)) = addOne(elem._1, elem._2) - override def addAll(xs: IterableOnce[(K, V)]): this.type = + override def addAll(xs: IterableOnce[(K, V)]^): this.type = if (switchedToHashMapBuilder) { hashMapBuilder.addAll(xs) this diff --git a/scala2-library-cc/src/scala/collection/immutable/NumericRange.scala b/scala2-library-cc/src/scala/collection/immutable/NumericRange.scala index d1ee494711a7..695083faf27d 100644 --- a/scala2-library-cc/src/scala/collection/immutable/NumericRange.scala +++ b/scala2-library-cc/src/scala/collection/immutable/NumericRange.scala @@ -14,6 +14,7 @@ package scala.collection.immutable import scala.collection.Stepper.EfficientSplit import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape} +import language.experimental.captureChecking /** `NumericRange` is a more generic version of the * `Range` class which works with arbitrary types. diff --git a/scala2-library-cc/src/scala/collection/immutable/Queue.scala b/scala2-library-cc/src/scala/collection/immutable/Queue.scala index 3d0f8206b6a9..785cca4b7c3e 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Queue.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Queue.scala @@ -15,6 +15,7 @@ package immutable import scala.collection.generic.DefaultSerializable import scala.collection.mutable.{Builder, ListBuffer} +import language.experimental.captureChecking /** `Queue` objects implement data structures that allow to * insert and retrieve elements in a first-in-first-out (FIFO) manner. @@ -119,7 +120,7 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L override def appended[B >: A](elem: B): Queue[B] = enqueue(elem) - override def appendedAll[B >: A](that: scala.collection.IterableOnce[B]): Queue[B] = { + override def appendedAll[B >: A](that: scala.collection.IterableOnce[B]^): Queue[B] = { val newIn = that match { case that: Queue[B] => that.in ++ (that.out reverse_::: this.in) case that: List[B] => that reverse_::: this.in @@ -202,7 +203,7 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L object Queue extends StrictOptimizedSeqFactory[Queue] { def newBuilder[A]: Builder[A, Queue[A]] = new ListBuffer[A] mapResult (x => new Queue[A](Nil, x)) - def from[A](source: IterableOnce[A]): Queue[A] = source match { + def from[A](source: IterableOnce[A]^): Queue[A] = source match { case q: Queue[A] => q case _ => val list = List.from(source) diff --git a/scala2-library-cc/src/scala/collection/immutable/Range.scala b/scala2-library-cc/src/scala/collection/immutable/Range.scala index 07bd340fa189..459591d1a9cb 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Range.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Range.scala @@ -17,6 +17,7 @@ import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl.RangeStepper import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape} import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** The `Range` class represents integer values in range * ''[start;end)'' with non-zero step value `step`. @@ -213,7 +214,7 @@ sealed abstract class Range( private[this] def posOf(i: Int): Int = if (contains(i)) (i - start) / step else -1 - override def sameElements[B >: Int](that: IterableOnce[B]): Boolean = that match { + override def sameElements[B >: Int](that: IterableOnce[B]^): Boolean = that match { case other: Range => (this.length : @annotation.switch) match { case 0 => other.isEmpty @@ -613,7 +614,7 @@ object Range { // As there is no appealing default step size for not-really-integral ranges, // we offer a partially constructed object. - class Partial[T, U](private val f: T => U) extends AnyVal { + class Partial[T, U](private val f: T -> U) extends AnyVal { def by(x: T): U = f(x) override def toString = "Range requires step" } @@ -667,6 +668,6 @@ private class RangeIterator( _hasNext = longPos >= lastElement } } - this + this } } diff --git a/scala2-library-cc/src/scala/collection/immutable/RedBlackTree.scala b/scala2-library-cc/src/scala/collection/immutable/RedBlackTree.scala index 20a3467638c2..69e93093f60c 100644 --- a/scala2-library-cc/src/scala/collection/immutable/RedBlackTree.scala +++ b/scala2-library-cc/src/scala/collection/immutable/RedBlackTree.scala @@ -17,6 +17,7 @@ package immutable import scala.annotation.meta.{getter, setter} import scala.annotation.tailrec import scala.runtime.Statics.releaseFence +import language.experimental.captureChecking /** An object containing the RedBlack tree implementation used by for `TreeMaps` and `TreeSets`. * @@ -567,8 +568,8 @@ private[collection] object RedBlackTree { override def toString: String = s"${if(isRed) "RedTree" else "BlackTree"}($key, $value, $left, $right)" //mutable APIs - private[RedBlackTree] def makeImmutable: this.type = { - def makeImmutableImpl(): Unit = { + private[RedBlackTree] def makeImmutable: Tree[A, B] = { + def makeImmutableImpl() = { if (isMutable) { var size = 1 if (_left ne null) { @@ -581,6 +582,7 @@ private[collection] object RedBlackTree { } _count |= size //retains colour } + this } makeImmutableImpl() this @@ -836,7 +838,8 @@ private[collection] object RedBlackTree { new Array[Tree[A, B]](maximumHeight) } private[this] var index = 0 - protected var lookahead: Tree[A, B] = if (start.isDefined) startFrom(start.get) else findLeftMostOrPopOnEmpty(root) + protected var lookahead: Tree[A, B] = + if (start.isDefined) startFrom(start.get) else findLeftMostOrPopOnEmpty(root) /** * Find the leftmost subtree whose key is equal to the given key, or if no such thing, @@ -863,7 +866,7 @@ private[collection] object RedBlackTree { } private[this] class EqualsIterator[A: Ordering, B](tree: Tree[A, B]) extends TreeIterator[A, B, Unit](tree, None) { - override def nextResult(tree: Tree[A, B]): Nothing = ??? + override def nextResult(tree: Tree[A, B]) = ??? def sameKeys[X](that:EqualsIterator[A,X]): Boolean = { var equal = true diff --git a/scala2-library-cc/src/scala/collection/immutable/Seq.scala b/scala2-library-cc/src/scala/collection/immutable/Seq.scala index 925fd648c70c..d575c3aaf14a 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Seq.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Seq.scala @@ -14,6 +14,8 @@ package scala package collection package immutable +import language.experimental.captureChecking + trait Seq[+A] extends Iterable[A] with collection.Seq[A] with SeqOps[A, Seq, Seq[A]] @@ -37,7 +39,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with collection.SeqOps[A, CC, C] */ @SerialVersionUID(3L) object Seq extends SeqFactory.Delegate[Seq](List) { - override def from[E](it: IterableOnce[E]): Seq[E] = it match { + override def from[E](it: IterableOnce[E]^): Seq[E] = it match { case s: Seq[E] => s case _ => super.from(it) } @@ -57,7 +59,7 @@ trait IndexedSeq[+A] extends Seq[A] } - override def sameElements[B >: A](o: IterableOnce[B]): Boolean = o match { + override def sameElements[B >: A](o: IterableOnce[B]^): Boolean = o match { case that: IndexedSeq[_] => (this eq that) || { val length = this.length @@ -110,7 +112,7 @@ object IndexedSeqDefaults { @SerialVersionUID(3L) object IndexedSeq extends SeqFactory.Delegate[IndexedSeq](Vector) { - override def from[E](it: IterableOnce[E]): IndexedSeq[E] = it match { + override def from[E](it: IterableOnce[E]^): IndexedSeq[E] = it match { case is: IndexedSeq[E] => is case _ => super.from(it) } @@ -141,14 +143,14 @@ trait LinearSeq[+A] @SerialVersionUID(3L) object LinearSeq extends SeqFactory.Delegate[LinearSeq](List) { - override def from[E](it: IterableOnce[E]): LinearSeq[E] = it match { + override def from[E](it: IterableOnce[E]^): LinearSeq[E] = it match { case ls: LinearSeq[E] => ls case _ => super.from(it) } } trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeqOps[A, CC, C]] - extends Any with SeqOps[A, CC, C] + extends AnyRef with SeqOps[A, CC, C] with collection.LinearSeqOps[A, CC, C] /** Explicit instantiation of the `Seq` trait to reduce class file size in subclasses. */ diff --git a/scala2-library-cc/src/scala/collection/immutable/SeqMap.scala b/scala2-library-cc/src/scala/collection/immutable/SeqMap.scala index 654bfa3baa21..fdd628f32698 100644 --- a/scala2-library-cc/src/scala/collection/immutable/SeqMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/SeqMap.scala @@ -15,6 +15,7 @@ package collection package immutable import scala.collection.mutable.{Builder, ReusableBuilder} +import language.experimental.captureChecking /** A base trait for ordered, immutable maps. * @@ -44,17 +45,9 @@ trait SeqMap[K, +V] object SeqMap extends MapFactory[SeqMap] { def empty[K, V]: SeqMap[K, V] = EmptySeqMap.asInstanceOf[SeqMap[K, V]] - def from[K, V](it: collection.IterableOnce[(K, V)]): SeqMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): SeqMap[K, V] = it match { - //case sm: SeqMap[K, V] => sm - case m: ListMap[K, V] => m - case m: TreeSeqMap[K, V] => m - case m: VectorMap[K, V] => m - case m: SeqMap1[K, V] => m - case m: SeqMap2[K, V] => m - case m: SeqMap3[K, V] => m - case m: SeqMap4[K, V] => m - case it: Iterable[_] if it.isEmpty => empty[K, V] + case sm: SeqMap[K, V] => sm case _ => (newBuilder[K, V] ++= it).result() } @@ -74,7 +67,7 @@ object SeqMap extends MapFactory[SeqMap] { } @SerialVersionUID(3L) - private[immutable] final class SeqMap1[K, +V](key1: K, value1: V) extends SeqMap[K,V] with Serializable { + private final class SeqMap1[K, +V](key1: K, value1: V) extends SeqMap[K,V] with Serializable { override def size: Int = 1 override def knownSize: Int = 1 override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key) @@ -98,7 +91,7 @@ object SeqMap extends MapFactory[SeqMap] { } @SerialVersionUID(3L) - private[immutable] final class SeqMap2[K, +V](key1: K, value1: V, key2: K, value2: V) extends SeqMap[K,V] with Serializable { + private final class SeqMap2[K, +V](key1: K, value1: V, key2: K, value2: V) extends SeqMap[K,V] with Serializable { override def size: Int = 2 override def knownSize: Int = 2 override def apply(key: K) = @@ -133,7 +126,7 @@ object SeqMap extends MapFactory[SeqMap] { } @SerialVersionUID(3L) - private[immutable] class SeqMap3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends SeqMap[K,V] with Serializable { + private class SeqMap3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends SeqMap[K,V] with Serializable { override def size: Int = 3 override def knownSize: Int = 3 override def apply(key: K) = @@ -174,7 +167,7 @@ object SeqMap extends MapFactory[SeqMap] { } @SerialVersionUID(3L) - private[immutable] final class SeqMap4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends SeqMap[K,V] with Serializable { + private final class SeqMap4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends SeqMap[K,V] with Serializable { override def size: Int = 4 override def knownSize: Int = 4 override def apply(key: K) = @@ -273,7 +266,7 @@ object SeqMap extends MapFactory[SeqMap] { this } - override def addAll(xs: IterableOnce[(K, V)]): this.type = + override def addAll(xs: IterableOnce[(K, V)]^): this.type = if (switchedToVectorMapBuilder) { vectorMapBuilder.addAll(xs) this diff --git a/scala2-library-cc/src/scala/collection/immutable/Set.scala b/scala2-library-cc/src/scala/collection/immutable/Set.scala index 707ddf40354f..4632a35f8484 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Set.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Set.scala @@ -16,6 +16,7 @@ package immutable import scala.collection.immutable.Set.Set4 import scala.collection.mutable.{Builder, ReusableBuilder} +import language.experimental.captureChecking /** Base trait for immutable set collections */ trait Set[A] extends Iterable[A] @@ -94,23 +95,14 @@ object Set extends IterableFactory[Set] { def empty[A]: Set[A] = EmptySet.asInstanceOf[Set[A]] - def from[E](it: collection.IterableOnce[E]): Set[E] = + def from[E](it: collection.IterableOnce[E]^): Set[E] = it match { - case _ if it.knownSize == 0 => empty[E] - // Since IterableOnce[E] launders the variance of E, - // identify only our implementations which can be soundly substituted. - // It's not sufficient to match `SortedSet[E]` to rebuild and `Set[E]` to retain. - case s: HashSet[E] => s - case s: ListSet[E] => s - case s: Set1[E] => s - case s: Set2[E] => s - case s: Set3[E] => s - case s: Set4[E] => s - case s: HashMap[E @unchecked, _]#HashKeySet => s - case s: MapOps[E, Any, Map, Map[E, Any]]#ImmutableKeySet @unchecked => s - // We also want `SortedSet` (and subclasses, such as `BitSet`) - // to rebuild themselves, to avoid element type widening issues. - case _ => newBuilder[E].addAll(it).result() + // We want `SortedSet` (and subclasses, such as `BitSet`) to + // rebuild themselves to avoid element type widening issues + case _: SortedSet[E] => (newBuilder[E] ++= it).result() + case _ if it.knownSize == 0 => empty[E] + case s: Set[E] => s + case _ => (newBuilder[E] ++= it).result() } def newBuilder[A]: Builder[A, Set[A]] = new SetBuilderImpl[A] @@ -137,7 +129,7 @@ object Set extends IterableFactory[Set] { private[collection] def emptyInstance: Set[Any] = EmptySet @SerialVersionUID(3L) - private abstract class SetNIterator[A](n: Int) extends AbstractIterator[A] with Serializable { + private abstract class SetNIterator[A](n: Int) extends AbstractIterator[A], Serializable, Pure { private[this] var current = 0 private[this] var remainder = n override def knownSize: Int = remainder @@ -397,7 +389,7 @@ private final class SetBuilderImpl[A] extends ReusableBuilder[A, Set[A]] { this } - override def addAll(xs: IterableOnce[A]): this.type = + override def addAll(xs: IterableOnce[A]^): this.type = if (switchedToHashSetBuilder) { hashSetBuilder.addAll(xs) this diff --git a/scala2-library-cc/src/scala/collection/immutable/SortedMap.scala b/scala2-library-cc/src/scala/collection/immutable/SortedMap.scala index 666d8c55bfb0..9587502fd908 100644 --- a/scala2-library-cc/src/scala/collection/immutable/SortedMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/SortedMap.scala @@ -16,6 +16,7 @@ package immutable import scala.annotation.unchecked.uncheckedVariance import scala.collection.mutable.Builder +import language.experimental.captureChecking /** An immutable map whose key-value pairs are sorted according to an [[scala.math.Ordering]] on the keys. * @@ -69,7 +70,7 @@ trait SortedMap[K, +V] * @param d the function mapping keys to values, used for non-present keys * @return a wrapper of the map with a default value */ - override def withDefault[V1 >: V](d: K => V1): SortedMap[K, V1] = new SortedMap.WithDefault[K, V1](this, d) + override def withDefault[V1 >: V](d: K -> V1): SortedMap[K, V1] = new SortedMap.WithDefault[K, V1](this, d) /** The same map with a given default value. * Note: The default is only used for `apply`. Other methods like `get`, `contains`, `iterator`, `keys`, etc. @@ -123,7 +124,7 @@ trait StrictOptimizedSortedMapOps[K, +V, +CC[X, +Y] <: Map[X, Y] with SortedMapO with collection.StrictOptimizedSortedMapOps[K, V, CC, C] with StrictOptimizedMapOps[K, V, Map, C] { - override def concat[V2 >: V](xs: collection.IterableOnce[(K, V2)]): CC[K, V2] = { + override def concat[V2 >: V](xs: collection.IterableOnce[(K, V2)]^): CC[K, V2] = { var result: CC[K, V2] = coll val it = xs.iterator while (it.hasNext) result = result + it.next() @@ -134,12 +135,12 @@ trait StrictOptimizedSortedMapOps[K, +V, +CC[X, +Y] <: Map[X, Y] with SortedMapO @SerialVersionUID(3L) object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { - override def from[K: Ordering, V](it: IterableOnce[(K, V)]): SortedMap[K, V] = it match { + override def from[K: Ordering, V](it: IterableOnce[(K, V)]^): SortedMap[K, V] = it match { case sm: SortedMap[K, V] if Ordering[K] == sm.ordering => sm case _ => super.from(it) } - final class WithDefault[K, +V](underlying: SortedMap[K, V], defaultValue: K => V) + final class WithDefault[K, +V](underlying: SortedMap[K, V], defaultValue: K -> V) extends Map.WithDefault[K, V](underlying, defaultValue) with SortedMap[K, V] with SortedMapOps[K, V, SortedMap, WithDefault[K, V]] with Serializable { @@ -161,14 +162,14 @@ object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { override def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = new WithDefault[K, V1](underlying.updated(key, value), defaultValue) - override def concat [V2 >: V](xs: collection.IterableOnce[(K, V2)]): WithDefault[K, V2] = + override def concat [V2 >: V](xs: collection.IterableOnce[(K, V2)]^): WithDefault[K, V2] = new WithDefault( underlying.concat(xs) , defaultValue) override def removed(key: K): WithDefault[K, V] = new WithDefault[K, V](underlying.removed(key), defaultValue) override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) - override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)] @uncheckedVariance): WithDefault[K, V] = + override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V) @uncheckedVariance]^): WithDefault[K, V] = new WithDefault[K, V](sortedMapFactory.from(coll), defaultValue) override protected def newSpecificBuilder: Builder[(K, V), WithDefault[K, V]] @uncheckedVariance = diff --git a/scala2-library-cc/src/scala/collection/immutable/SortedSet.scala b/scala2-library-cc/src/scala/collection/immutable/SortedSet.scala index 303e5ea9658c..874abcaecda1 100644 --- a/scala2-library-cc/src/scala/collection/immutable/SortedSet.scala +++ b/scala2-library-cc/src/scala/collection/immutable/SortedSet.scala @@ -13,6 +13,7 @@ package scala package collection package immutable +import language.experimental.captureChecking /** Base trait for sorted sets */ trait SortedSet[A] @@ -50,7 +51,7 @@ trait StrictOptimizedSortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[ */ @SerialVersionUID(3L) object SortedSet extends SortedIterableFactory.Delegate[SortedSet](TreeSet) { - override def from[E: Ordering](it: IterableOnce[E]): SortedSet[E] = it match { + override def from[E: Ordering](it: IterableOnce[E]^): SortedSet[E] = it match { case ss: SortedSet[E] if Ordering[E] == ss.ordering => ss case _ => super.from(it) } diff --git a/scala2-library-cc/src/scala/collection/immutable/StrictOptimizedSeqOps.scala b/scala2-library-cc/src/scala/collection/immutable/StrictOptimizedSeqOps.scala index db5192edc36c..5ceb5435469f 100644 --- a/scala2-library-cc/src/scala/collection/immutable/StrictOptimizedSeqOps.scala +++ b/scala2-library-cc/src/scala/collection/immutable/StrictOptimizedSeqOps.scala @@ -13,6 +13,7 @@ package scala package collection package immutable +import language.experimental.captureChecking /** * Trait that overrides operations to take advantage of strict builders. @@ -23,7 +24,7 @@ trait StrictOptimizedSeqOps[+A, +CC[_], +C] with collection.StrictOptimizedSeqOps[A, CC, C] with StrictOptimizedIterableOps[A, CC, C] { - override def distinctBy[B](f: A => B): C = { + override def distinctBy[B](f: A -> B): C = { if (lengthCompare(1) <= 0) coll else { val builder = newSpecificBuilder @@ -57,7 +58,7 @@ trait StrictOptimizedSeqOps[+A, +CC[_], +C] b.result() } - override def patch[B >: A](from: Int, other: IterableOnce[B], replaced: Int): CC[B] = { + override def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] = { val b = iterableFactory.newBuilder[B] var i = 0 val it = iterator diff --git a/scala2-library-cc/src/scala/collection/immutable/TreeMap.scala b/scala2-library-cc/src/scala/collection/immutable/TreeMap.scala index a51c7b9e7bf6..8da2f189a985 100644 --- a/scala2-library-cc/src/scala/collection/immutable/TreeMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/TreeMap.scala @@ -20,6 +20,7 @@ import scala.collection.generic.DefaultSerializable import scala.collection.immutable.{RedBlackTree => RB} import scala.collection.mutable.ReusableBuilder import scala.runtime.AbstractFunction2 +import language.experimental.captureChecking /** An immutable SortedMap whose values are stored in a red-black tree. * @@ -138,7 +139,7 @@ final class TreeMap[K, +V] private (private val tree: RB.Tree[K, V])(implicit va def updated[V1 >: V](key: K, value: V1): TreeMap[K, V1] = newMapOrSelf(RB.update(tree, key, value, overwrite = true)) - override def concat[V1 >: V](that: collection.IterableOnce[(K, V1)]): TreeMap[K, V1] = + override def concat[V1 >: V](that: collection.IterableOnce[(K, V1)]^): TreeMap[K, V1] = newMapOrSelf(that match { case tm: TreeMap[K, V] @unchecked if ordering == tm.ordering => RB.union(tree, tm.tree) @@ -158,7 +159,7 @@ final class TreeMap[K, +V] private (private val tree: RB.Tree[K, V])(implicit va adder.finalTree }) - override def removedAll(keys: IterableOnce[K]): TreeMap[K, V] = keys match { + override def removedAll(keys: IterableOnce[K]^): TreeMap[K, V] = keys match { case ts: TreeSet[K] if ordering == ts.ordering => newMapOrSelf(RB.difference(tree, ts.tree)) case _ => super.removedAll(keys) @@ -299,7 +300,7 @@ object TreeMap extends SortedMapFactory[TreeMap] { def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap() - def from[K, V](it: IterableOnce[(K, V)])(implicit ordering: Ordering[K]): TreeMap[K, V] = + def from[K, V](it: IterableOnce[(K, V)]^)(implicit ordering: Ordering[K]): TreeMap[K, V] = it match { case tm: TreeMap[K, V] if ordering == tm.ordering => tm case sm: scala.collection.SortedMap[K, V] if ordering == sm.ordering => @@ -329,7 +330,7 @@ object TreeMap extends SortedMapFactory[TreeMap] { private object adder extends AbstractFunction2[K, V, Unit] { // we cache tree to avoid the outer access to tree // in the hot path (apply) - private[this] var accumulator :Tree = null + private[this] var accumulator: Tree = null def addForEach(hasForEach: collection.Map[K, V]): Unit = { accumulator = tree hasForEach.foreachEntry(this) @@ -343,7 +344,7 @@ object TreeMap extends SortedMapFactory[TreeMap] { } } - override def addAll(xs: IterableOnce[(K, V)]): this.type = { + override def addAll(xs: IterableOnce[(K, V)]^): this.type = { xs match { // TODO consider writing a mutable-safe union for TreeSet/TreeMap builder ++= // for the moment we have to force immutability before the union diff --git a/scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala b/scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala index 80bafb1cf3be..dc59d21b8b19 100644 --- a/scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala @@ -15,6 +15,7 @@ package collection package immutable import scala.annotation.tailrec +import language.experimental.captureChecking /** This class implements an immutable map that preserves order using * a hash map for the key to value mapping to provide efficient lookup, @@ -233,7 +234,7 @@ final class TreeSeqMap[K, +V] private ( bdr.result() } - override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): TreeSeqMap[K2, V2] = { + override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): TreeSeqMap[K2, V2] = { val bdr = newBuilder[K2, V2](orderedBy) val iter = ordering.iterator while (iter.hasNext) { @@ -259,7 +260,7 @@ final class TreeSeqMap[K, +V] private ( bdr.result() } - override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]): TreeSeqMap[K, V2] = { + override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]^): TreeSeqMap[K, V2] = { var ong: Ordering[K] = ordering var mng: Mapping[K, V2] = mapping var ord = increment(ordinal) @@ -302,7 +303,7 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { else EmptyByInsertion }.asInstanceOf[TreeSeqMap[K, V]] - def from[K, V](it: collection.IterableOnce[(K, V)]): TreeSeqMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): TreeSeqMap[K, V] = it match { case om: TreeSeqMap[K, V] => om case _ => (newBuilder[K, V] ++= it).result() @@ -607,7 +608,7 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { } final def splitAt(n: Int): (Ordering[T], Ordering[T]) = { - var rear = Ordering.empty[T] + var rear: Ordering[T] = Ordering.empty[T] var i = n (modifyOrRemove { (o, v) => i -= 1 diff --git a/scala2-library-cc/src/scala/collection/immutable/TreeSet.scala b/scala2-library-cc/src/scala/collection/immutable/TreeSet.scala index 2a010cb3218b..097341283719 100644 --- a/scala2-library-cc/src/scala/collection/immutable/TreeSet.scala +++ b/scala2-library-cc/src/scala/collection/immutable/TreeSet.scala @@ -19,7 +19,7 @@ import scala.collection.generic.DefaultSerializable import scala.collection.mutable.ReusableBuilder import scala.collection.immutable.{RedBlackTree => RB} import scala.runtime.AbstractFunction1 - +import language.experimental.captureChecking /** This class implements immutable sorted sets using a tree. * @@ -48,7 +48,7 @@ final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[ def this()(implicit ordering: Ordering[A]) = this(null)(ordering) - override def sortedIterableFactory: TreeSet.type = TreeSet + override def sortedIterableFactory = TreeSet private[this] def newSetOrSelf(t: RB.Tree[A, Any]) = if(t eq tree) this else new TreeSet[A](t) @@ -239,7 +239,7 @@ object TreeSet extends SortedIterableFactory[TreeSet] { def empty[A: Ordering]: TreeSet[A] = new TreeSet[A] - def from[E](it: scala.collection.IterableOnce[E])(implicit ordering: Ordering[E]): TreeSet[E] = + def from[E](it: scala.collection.IterableOnce[E]^)(implicit ordering: Ordering[E]): TreeSet[E] = it match { case ts: TreeSet[E] if ordering == ts.ordering => ts case ss: scala.collection.SortedSet[E] if ordering == ss.ordering => @@ -269,7 +269,7 @@ object TreeSet extends SortedIterableFactory[TreeSet] { this } - override def addAll(xs: IterableOnce[A]): this.type = { + override def addAll(xs: IterableOnce[A]^): this.type = { xs match { // TODO consider writing a mutable-safe union for TreeSet/TreeMap builder ++= // for the moment we have to force immutability before the union diff --git a/scala2-library-cc/src/scala/collection/immutable/Vector.scala b/scala2-library-cc/src/scala/collection/immutable/Vector.scala index b3b164b00404..d584d4a446af 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Vector.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Vector.scala @@ -24,6 +24,7 @@ import scala.collection.generic.DefaultSerializable import scala.collection.immutable.VectorInline._ import scala.collection.immutable.VectorStatics._ import scala.collection.mutable.ReusableBuilder +import language.experimental.captureChecking /** $factoryInfo @@ -35,7 +36,7 @@ object Vector extends StrictOptimizedSeqFactory[Vector] { def empty[A]: Vector[A] = Vector0 - def from[E](it: collection.IterableOnce[E]): Vector[E] = + def from[E](it: collection.IterableOnce[E]^): Vector[E] = it match { case v: Vector[E] => v case _ => @@ -47,13 +48,11 @@ object Vector extends StrictOptimizedSeqFactory[Vector] { as.unsafeArray.asInstanceOf[Arr1] case it: Iterable[E] => val a1 = new Arr1(knownSize) - @annotation.unused val copied = it.copyToArray(a1.asInstanceOf[Array[Any]]) - //assert(copied == knownSize) + it.copyToArray(a1.asInstanceOf[Array[Any]]) a1 case _ => val a1 = new Arr1(knownSize) - @annotation.unused val copied = it.iterator.copyToArray(a1.asInstanceOf[Array[Any]]) - //assert(copied == knownSize) + it.iterator.copyToArray(a1.asInstanceOf[Array[Any]]) a1.asInstanceOf[Arr1] } new Vector1[E](a1) @@ -193,21 +192,21 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va override def updated[B >: A](index: Int, elem: B): Vector[B] = super.updated(index, elem) override def appended[B >: A](elem: B): Vector[B] = super.appended(elem) override def prepended[B >: A](elem: B): Vector[B] = super.prepended(elem) - override def prependedAll[B >: A](prefix: collection.IterableOnce[B]): Vector[B] = { + override def prependedAll[B >: A](prefix: collection.IterableOnce[B]^): Vector[B] = { val k = prefix.knownSize if (k == 0) this else if (k < 0) super.prependedAll(prefix) else prependedAll0(prefix, k) } - override final def appendedAll[B >: A](suffix: collection.IterableOnce[B]): Vector[B] = { + override final def appendedAll[B >: A](suffix: collection.IterableOnce[B]^): Vector[B] = { val k = suffix.knownSize if (k == 0) this else if (k < 0) super.appendedAll(suffix) else appendedAll0(suffix, k) } - protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = { + protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = { // k >= 0, k = prefix.knownSize val tinyAppendLimit = 4 + vectorSliceCount if (k < tinyAppendLimit /*|| k < (this.size >>> Log2ConcatFaster)*/) { @@ -225,7 +224,7 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va } else super.prependedAll(prefix) } - protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { // k >= 0, k = suffix.knownSize val tinyAppendLimit = 4 + vectorSliceCount if (k < tinyAppendLimit) { @@ -371,10 +370,10 @@ private object Vector0 extends BigVector[Nothing](empty1, empty1, 0) { } } - override protected[this]def prependedAll0[B >: Nothing](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this]def prependedAll0[B >: Nothing](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = Vector.from(prefix) - override protected[this]def appendedAll0[B >: Nothing](suffix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this]def appendedAll0[B >: Nothing](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = Vector.from(suffix) override protected[this] def ioob(index: Int): IndexOutOfBoundsException = @@ -425,13 +424,13 @@ private final class Vector1[+A](_data1: Arr1) extends VectorImpl[A](_data1) { protected[immutable] def vectorSlice(idx: Int): Array[_ <: AnyRef] = prefix1 protected[immutable] def vectorSlicePrefixLength(idx: Int): Int = prefix1.length - override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = prepend1IfSpace(prefix1, prefix) match { case null => super.prependedAll0(prefix, k) case data1b => new Vector1(data1b) } - override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { val data1b = append1IfSpace(prefix1, suffix) if(data1b ne null) new Vector1(data1b) else super.appendedAll0(suffix, k) @@ -520,7 +519,7 @@ private final class Vector2[+A](_prefix1: Arr1, private[immutable] val len1: Int case 2 => length0 } - override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = prepend1IfSpace(prefix1, prefix) match { case null => super.prependedAll0(prefix, k) case prefix1b => @@ -531,7 +530,7 @@ private final class Vector2[+A](_prefix1: Arr1, private[immutable] val len1: Int ) } - override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { val suffix1b = append1IfSpace(suffix1, suffix) if(suffix1b ne null) copy(suffix1 = suffix1b, length0 = length0-suffix1.length+suffix1b.length) else super.appendedAll0(suffix, k) @@ -642,7 +641,7 @@ private final class Vector3[+A](_prefix1: Arr1, private[immutable] val len1: Int case 4 => length0 } - override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = prepend1IfSpace(prefix1, prefix) match { case null => super.prependedAll0(prefix, k) case prefix1b => @@ -654,7 +653,7 @@ private final class Vector3[+A](_prefix1: Arr1, private[immutable] val len1: Int ) } - override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { val suffix1b = append1IfSpace(suffix1, suffix) if(suffix1b ne null) copy(suffix1 = suffix1b, length0 = length0-suffix1.length+suffix1b.length) else super.appendedAll0(suffix, k) @@ -785,7 +784,7 @@ private final class Vector4[+A](_prefix1: Arr1, private[immutable] val len1: Int case 6 => length0 } - override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = prepend1IfSpace(prefix1, prefix) match { case null => super.prependedAll0(prefix, k) case prefix1b => @@ -798,7 +797,7 @@ private final class Vector4[+A](_prefix1: Arr1, private[immutable] val len1: Int ) } - override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { val suffix1b = append1IfSpace(suffix1, suffix) if(suffix1b ne null) copy(suffix1 = suffix1b, length0 = length0-suffix1.length+suffix1b.length) else super.appendedAll0(suffix, k) @@ -949,7 +948,7 @@ private final class Vector5[+A](_prefix1: Arr1, private[immutable] val len1: Int case 8 => length0 } - override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = prepend1IfSpace(prefix1, prefix) match { case null => super.prependedAll0(prefix, k) case prefix1b => @@ -963,7 +962,7 @@ private final class Vector5[+A](_prefix1: Arr1, private[immutable] val len1: Int ) } - override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { val suffix1b = append1IfSpace(suffix1, suffix) if(suffix1b ne null) copy(suffix1 = suffix1b, length0 = length0-suffix1.length+suffix1b.length) else super.appendedAll0(suffix, k) @@ -1134,7 +1133,7 @@ private final class Vector6[+A](_prefix1: Arr1, private[immutable] val len1: Int case 10 => length0 } - override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = + override protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B]^, k: Int): Vector[B] = prepend1IfSpace(prefix1, prefix) match { case null => super.prependedAll0(prefix, k) case prefix1b => @@ -1149,7 +1148,7 @@ private final class Vector6[+A](_prefix1: Arr1, private[immutable] val len1: Int ) } - override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = { + override protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B]^, k: Int): Vector[B] = { val suffix1b = append1IfSpace(suffix1, suffix) if(suffix1b ne null) copy(suffix1 = suffix1b, length0 = length0-suffix1.length+suffix1b.length) else super.appendedAll0(suffix, k) @@ -1816,7 +1815,7 @@ final class VectorBuilder[A] extends ReusableBuilder[A, Vector[A]] { this } - override def addAll(xs: IterableOnce[A]): this.type = xs match { + override def addAll(xs: IterableOnce[A]^): this.type = xs match { case v: Vector[_] => if(len1 == 0 && lenRest == 0 && !prefixIsRightAligned) initFrom(v) else addVector(v.asInstanceOf[Vector[A]]) @@ -2185,7 +2184,7 @@ private object VectorStatics { ac.asInstanceOf[Array[T]] } - final def prepend1IfSpace(prefix1: Arr1, xs: IterableOnce[_]): Arr1 = xs match { + final def prepend1IfSpace(prefix1: Arr1, xs: IterableOnce[_]^): Arr1 = xs match { case it: Iterable[_] => if(it.sizeCompare(WIDTH-prefix1.length) <= 0) { it.size match { @@ -2194,8 +2193,7 @@ private object VectorStatics { case s => val prefix1b = new Arr1(prefix1.length + s) System.arraycopy(prefix1, 0, prefix1b, s, prefix1.length) - @annotation.unused val copied = it.copyToArray(prefix1b.asInstanceOf[Array[Any]], 0) - //assert(copied == s) + it.copyToArray(prefix1b.asInstanceOf[Array[Any]], 0) prefix1b } } else null @@ -2204,13 +2202,12 @@ private object VectorStatics { if(s > 0 && s <= WIDTH-prefix1.length) { val prefix1b = new Arr1(prefix1.length + s) System.arraycopy(prefix1, 0, prefix1b, s, prefix1.length) - @annotation.unused val copied = it.iterator.copyToArray(prefix1b.asInstanceOf[Array[Any]], 0) - //assert(copied == s) + it.iterator.copyToArray(prefix1b.asInstanceOf[Array[Any]], 0) prefix1b } else null } - final def append1IfSpace(suffix1: Arr1, xs: IterableOnce[_]): Arr1 = xs match { + final def append1IfSpace(suffix1: Arr1, xs: IterableOnce[_]^): Arr1 = xs match { case it: Iterable[_] => if(it.sizeCompare(WIDTH-suffix1.length) <= 0) { it.size match { @@ -2218,8 +2215,7 @@ private object VectorStatics { case 1 => copyAppend(suffix1, it.head.asInstanceOf[AnyRef]) case s => val suffix1b = copyOf(suffix1, suffix1.length + s) - @annotation.unused val copied = it.copyToArray(suffix1b.asInstanceOf[Array[Any]], suffix1.length) - //assert(copied == s) + it.copyToArray(suffix1b.asInstanceOf[Array[Any]], suffix1.length) suffix1b } } else null @@ -2227,15 +2223,14 @@ private object VectorStatics { val s = it.knownSize if(s > 0 && s <= WIDTH-suffix1.length) { val suffix1b = copyOf(suffix1, suffix1.length + s) - @annotation.unused val copied = it.iterator.copyToArray(suffix1b.asInstanceOf[Array[Any]], suffix1.length) - //assert(copied == s) + it.iterator.copyToArray(suffix1b.asInstanceOf[Array[Any]], suffix1.length) suffix1b } else null } } -private final class NewVectorIterator[A](v: Vector[A], private[this] var totalLength: Int, private[this] val sliceCount: Int) extends AbstractIterator[A] with java.lang.Cloneable { +private final class NewVectorIterator[A](v: Vector[A], private[this] var totalLength: Int, private[this] val sliceCount: Int) extends Iterator[A] with java.lang.Cloneable { private[this] var a1: Arr1 = v.prefix1 private[this] var a2: Arr2 = _ diff --git a/scala2-library-cc/src/scala/collection/immutable/VectorMap.scala b/scala2-library-cc/src/scala/collection/immutable/VectorMap.scala index cd8cf06c5c68..2bbcf429e01d 100644 --- a/scala2-library-cc/src/scala/collection/immutable/VectorMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/VectorMap.scala @@ -15,6 +15,7 @@ package collection package immutable import scala.annotation.tailrec +import language.experimental.captureChecking /** This class implements immutable maps using a vector/map-based data structure, which preserves insertion order. * @@ -58,7 +59,7 @@ final class VectorMap[K, +V] private ( } } - override def withDefault[V1 >: V](d: K => V1): Map[K, V1] = + override def withDefault[V1 >: V](d: K -> V1): Map[K, V1] = new Map.WithDefault(this, d) override def withDefaultValue[V1 >: V](d: V1): Map[K, V1] = @@ -229,7 +230,7 @@ object VectorMap extends MapFactory[VectorMap] { def empty[K, V]: VectorMap[K, V] = EmptyMap.asInstanceOf[VectorMap[K, V]] - def from[K, V](it: collection.IterableOnce[(K, V)]): VectorMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): VectorMap[K, V] = it match { case vm: VectorMap[K, V] => vm case _ => (newBuilder[K, V] ++= it).result() @@ -241,7 +242,7 @@ object VectorMap extends MapFactory[VectorMap] { private[immutable] final class VectorMapBuilder[K, V] extends mutable.Builder[(K, V), VectorMap[K, V]] { private[this] val vectorBuilder = new VectorBuilder[K] private[this] val mapBuilder = new MapBuilderImpl[K, (Int, V)] - private[this] var aliased: VectorMap[K, V] = _ + private[this] var aliased: VectorMap[K, V] = _ // OK since VectorMapBuilder is private override def clear(): Unit = { vectorBuilder.clear() diff --git a/scala2-library-cc/src/scala/collection/immutable/WrappedString.scala b/scala2-library-cc/src/scala/collection/immutable/WrappedString.scala index f2fdb8e3c32e..446bdceb3ace 100644 --- a/scala2-library-cc/src/scala/collection/immutable/WrappedString.scala +++ b/scala2-library-cc/src/scala/collection/immutable/WrappedString.scala @@ -17,6 +17,7 @@ import scala.Predef.{wrapString => _, assert} import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl.CharStringStepper import scala.collection.mutable.{Builder, StringBuilder} +import language.experimental.captureChecking /** * This class serves as a wrapper augmenting `String`s with all the operations @@ -34,11 +35,12 @@ import scala.collection.mutable.{Builder, StringBuilder} @SerialVersionUID(3L) final class WrappedString(private val self: String) extends AbstractSeq[Char] with IndexedSeq[Char] with IndexedSeqOps[Char, IndexedSeq, WrappedString] - with Serializable { + with Serializable + with Pure { def apply(i: Int): Char = self.charAt(i) - override protected def fromSpecific(coll: scala.collection.IterableOnce[Char]): WrappedString = WrappedString.fromSpecific(coll) + override protected def fromSpecific(coll: scala.collection.IterableOnce[Char]^): WrappedString = WrappedString.fromSpecific(coll) override protected def newSpecificBuilder: Builder[Char, WrappedString] = WrappedString.newBuilder override def empty: WrappedString = WrappedString.empty @@ -65,13 +67,13 @@ final class WrappedString(private val self: String) extends AbstractSeq[Char] wi r.asInstanceOf[S with EfficientSplit] } - override def startsWith[B >: Char](that: IterableOnce[B], offset: Int = 0): Boolean = + override def startsWith[B >: Char](that: IterableOnce[B]^, offset: Int = 0): Boolean = that match { case s: WrappedString => self.startsWith(s.self, offset) case _ => super.startsWith(that, offset) } - override def endsWith[B >: Char](that: collection.Iterable[B]): Boolean = + override def endsWith[B >: Char](that: collection.Iterable[B]^): Boolean = that match { case s: WrappedString => self.endsWith(s.self) case _ => super.endsWith(that) @@ -97,13 +99,13 @@ final class WrappedString(private val self: String) extends AbstractSeq[Char] wi case _ => super.copyToArray(xs, start, len) } - override def appendedAll[B >: Char](suffix: IterableOnce[B]): IndexedSeq[B] = + override def appendedAll[B >: Char](suffix: IterableOnce[B]^): IndexedSeq[B] = suffix match { case s: WrappedString => new WrappedString(self concat s.self) case _ => super.appendedAll(suffix) } - override def sameElements[B >: Char](o: IterableOnce[B]) = o match { + override def sameElements[B >: Char](o: IterableOnce[B]^) = o match { case s: WrappedString => self == s.self case _ => super.sameElements(o) } @@ -123,7 +125,7 @@ final class WrappedString(private val self: String) extends AbstractSeq[Char] wi */ @SerialVersionUID(3L) object WrappedString extends SpecificIterableFactory[Char, WrappedString] { - def fromSpecific(it: IterableOnce[Char]): WrappedString = { + def fromSpecific(it: IterableOnce[Char]^): WrappedString = { val b = newBuilder val s = it.knownSize if(s >= 0) b.sizeHint(s) diff --git a/scala2-library-cc/src/scala/collection/immutable/package.scala b/scala2-library-cc/src/scala/collection/immutable/package.scala index 8458429727e8..985ef22859be 100644 --- a/scala2-library-cc/src/scala/collection/immutable/package.scala +++ b/scala2-library-cc/src/scala/collection/immutable/package.scala @@ -11,7 +11,7 @@ */ package scala.collection - +import language.experimental.captureChecking package object immutable { type StringOps = scala.collection.StringOps diff --git a/scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala b/scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala index fc102dabe250..480babbf4b91 100644 --- a/scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala @@ -17,6 +17,8 @@ package mutable import scala.annotation.nowarn import scala.collection.generic.DefaultSerializationProxy import scala.language.implicitConversions +import language.experimental.captureChecking + /** This class implements mutable maps with `AnyRef` keys based on a hash table with open addressing. * @@ -41,7 +43,7 @@ import scala.language.implicitConversions * rapidly as 2^30^ is approached. * */ -class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initialBufferSize: Int, initBlank: Boolean) +class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K -> V, initialBufferSize: Int, initBlank: Boolean) extends AbstractMap[K, V] with MapOps[K, V, Map, AnyRefMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, AnyRefMap[K, V]] @@ -51,7 +53,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi def this() = this(AnyRefMap.exceptionDefault, 16, true) /** Creates a new `AnyRefMap` that returns default values according to a supplied key-value mapping. */ - def this(defaultEntry: K => V) = this(defaultEntry, 16, true) + def this(defaultEntry: K -> V) = this(defaultEntry, 16, true) /** Creates a new `AnyRefMap` with an initial buffer of specified size. * @@ -61,7 +63,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi def this(initialBufferSize: Int) = this(AnyRefMap.exceptionDefault, initialBufferSize, true) /** Creates a new `AnyRefMap` with specified default values and initial buffer size. */ - def this(defaultEntry: K => V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, true) + def this(defaultEntry: K -> V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, true) private[this] var mask = 0 private[this] var _size = 0 @@ -87,7 +89,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi mask = m; _size = sz; _vacant = vc; _hashes = hz; _keys = kz; _values = vz } - override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)]): AnyRefMap[K,V] = { + override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)]^): AnyRefMap[K,V] = { var sz = coll.knownSize if(sz < 0) sz = 4 val arm = new AnyRefMap[K, V](sz * 2) @@ -401,13 +403,13 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi if(elems.isEmpty) m else m.concat(elems) } - override def concat[V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]): AnyRefMap[K, V2] = { + override def concat[V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]^): AnyRefMap[K, V2] = { val arm = clone().asInstanceOf[AnyRefMap[K, V2]] xs.iterator.foreach(kv => arm += kv) arm } - override def ++[V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]): AnyRefMap[K, V2] = concat(xs) + override def ++[V2 >: V](xs: scala.collection.IterableOnce[(K, V2)]^): AnyRefMap[K, V2] = concat(xs) @deprecated("Use m.clone().addOne(k,v) instead of m.updated(k, v)", "2.13.0") override def updated[V1 >: V](key: K, value: V1): AnyRefMap[K, V1] = @@ -504,7 +506,7 @@ object AnyRefMap { private final val VacantBit = 0x40000000 private final val MissVacant = 0xC0000000 - private class ExceptionDefault extends (Any => Nothing) with Serializable { + private class ExceptionDefault extends (Any -> Nothing) with Serializable { def apply(k: Any): Nothing = throw new NoSuchElementException(if (k == null) "(null)" else k.toString) } private val exceptionDefault = new ExceptionDefault @@ -529,7 +531,7 @@ object AnyRefMap { def newBuilder[K <: AnyRef, V]: ReusableBuilder[(K, V), AnyRefMap[K, V]] = new AnyRefMapBuilder[K, V] - private def buildFromIterableOnce[K <: AnyRef, V](elems: IterableOnce[(K, V)]): AnyRefMap[K, V] = { + private def buildFromIterableOnce[K <: AnyRef, V](elems: IterableOnce[(K, V)]^): AnyRefMap[K, V] = { var sz = elems.knownSize if(sz < 0) sz = 4 val arm = new AnyRefMap[K, V](sz * 2) @@ -542,7 +544,7 @@ object AnyRefMap { def empty[K <: AnyRef, V]: AnyRefMap[K, V] = new AnyRefMap[K, V] /** Creates a new empty `AnyRefMap` with the supplied default */ - def withDefault[K <: AnyRef, V](default: K => V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) + def withDefault[K <: AnyRef, V](default: K -> V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) /** Creates a new `AnyRefMap` from an existing source collection. A source collection * which is already an `AnyRefMap` gets cloned. @@ -552,7 +554,7 @@ object AnyRefMap { * @tparam V the type of the values * @return a new `AnyRefMap` with the elements of `source` */ - def from[K <: AnyRef, V](source: IterableOnce[(K, V)]): AnyRefMap[K, V] = source match { + def from[K <: AnyRef, V](source: IterableOnce[(K, V)]^): AnyRefMap[K, V] = source match { case source: AnyRefMap[_, _] => source.clone().asInstanceOf[AnyRefMap[K, V]] case _ => buildFromIterableOnce(source) } @@ -572,7 +574,7 @@ object AnyRefMap { /** Creates a new `AnyRefMap` from keys and values. * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. */ - def fromZip[K <: AnyRef, V](keys: Iterable[K], values: Iterable[V]): AnyRefMap[K, V] = { + def fromZip[K <: AnyRef, V](keys: Iterable[K]^, values: Iterable[V]^): AnyRefMap[K, V] = { val sz = math.min(keys.size, values.size) val arm = new AnyRefMap[K, V](sz * 2) val ki = keys.iterator @@ -586,14 +588,14 @@ object AnyRefMap { @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] with Serializable { - def fromSpecific(it: IterableOnce[(AnyRef, AnyRef)]): AnyRefMap[AnyRef, AnyRef] = AnyRefMap.from[AnyRef, AnyRef](it) + def fromSpecific(it: IterableOnce[(AnyRef, AnyRef)]^): AnyRefMap[AnyRef, AnyRef] = AnyRefMap.from[AnyRef, AnyRef](it) def newBuilder: Builder[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] = AnyRefMap.newBuilder[AnyRef, AnyRef] } implicit def toBuildFrom[K <: AnyRef, V](factory: AnyRefMap.type): BuildFrom[Any, (K, V), AnyRefMap[K, V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (K, V), AnyRefMap[K, V]]] private[this] object ToBuildFrom extends BuildFrom[Any, (AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] { - def fromSpecific(from: Any)(it: IterableOnce[(AnyRef, AnyRef)]): AnyRefMap[AnyRef, AnyRef] = AnyRefMap.from(it) - def newBuilder(from: Any): ReusableBuilder[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] = AnyRefMap.newBuilder[AnyRef, AnyRef] + def fromSpecific(from: Any)(it: IterableOnce[(AnyRef, AnyRef)]^) = AnyRefMap.from(it) + def newBuilder(from: Any) = AnyRefMap.newBuilder[AnyRef, AnyRef] } implicit def iterableFactory[K <: AnyRef, V]: Factory[(K, V), AnyRefMap[K, V]] = toFactory[K, V](this) diff --git a/scala2-library-cc/src/scala/collection/mutable/ArrayBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/ArrayBuffer.scala index e3ddeb71ef8e..85a045c34423 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ArrayBuffer.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ArrayBuffer.scala @@ -20,6 +20,7 @@ import scala.annotation.nowarn import scala.annotation.tailrec import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable +import language.experimental.captureChecking /** An implementation of the `Buffer` class using an array to * represent the assembled sequence internally. Append, update and random @@ -151,7 +152,7 @@ class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int) } // Overridden to use array copying for efficiency where possible. - override def addAll(elems: IterableOnce[A]): this.type = { + override def addAll(elems: IterableOnce[A]^): this.type = { elems match { case elems: ArrayBuffer[_] => val elemsLength = elems.size0 @@ -180,7 +181,7 @@ class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int) this } - def insertAll(@deprecatedName("n", "2.13.0") index: Int, elems: IterableOnce[A]): Unit = { + def insertAll(@deprecatedName("n", "2.13.0") index: Int, elems: IterableOnce[A]^): Unit = { checkWithinBounds(index, index) elems match { case elems: collection.Iterable[A] => @@ -234,7 +235,7 @@ class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int) @deprecated("Use 'new GrowableBuilder(this).mapResult(f)' instead", "2.13.0") @deprecatedOverriding("ArrayBuffer[A] no longer extends Builder[A, ArrayBuffer[A]]", "2.13.0") - @inline def mapResult[NewTo](f: (ArrayBuffer[A]) => NewTo): Builder[A, NewTo] = new GrowableBuilder[A, ArrayBuffer[A]](this).mapResult(f) + @inline def mapResult[NewTo](f: (ArrayBuffer[A]) => NewTo): Builder[A, NewTo]^{f} = new GrowableBuilder[A, ArrayBuffer[A]](this).mapResult(f) @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix = "ArrayBuffer" @@ -291,7 +292,7 @@ object ArrayBuffer extends StrictOptimizedSeqFactory[ArrayBuffer] { final val DefaultInitialSize = 16 private[this] val emptyArray = new Array[AnyRef](0) - def from[B](coll: collection.IterableOnce[B]): ArrayBuffer[B] = { + def from[B](coll: collection.IterableOnce[B]^): ArrayBuffer[B] = { val k = coll.knownSize if (k >= 0) { // Avoid reallocation of buffer if length is known @@ -357,22 +358,23 @@ object ArrayBuffer extends StrictOptimizedSeqFactory[ArrayBuffer] { } // TODO: use `CheckedIndexedSeqView.Id` once we can change the return type of `ArrayBuffer#view` -final class ArrayBufferView[A] private[mutable](underlying: ArrayBuffer[A], mutationCount: () => Int) - extends AbstractIndexedSeqView[A] { +final class ArrayBufferView[A] private[mutable](underlying: ArrayBuffer[A], mutationCount: () -> Int) + extends AbstractIndexedSeqView[A], Pure { + /* Removed since it poses problems for capture checking @deprecated("never intended to be public; call ArrayBuffer#view instead", since = "2.13.7") def this(array: Array[AnyRef], length: Int) = { // this won't actually track mutation, but it would be a pain to have the implementation // check if we have a method to get the current mutation count or not on every method and // change what it does based on that. hopefully no one ever calls this. this({ - val _array = array + val _array: Array[Object] = array val _length = length new ArrayBuffer[A](0) { this.array = _array this.size0 = _length - } + }: ArrayBuffer[A] }, () => 0) - } + }*/ @deprecated("never intended to be public", since = "2.13.7") def array: Array[AnyRef] = underlying.toArray[Any].asInstanceOf[Array[AnyRef]] @@ -392,10 +394,10 @@ final class ArrayBufferView[A] private[mutable](underlying: ArrayBuffer[A], muta override def takeRight(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.TakeRight(this, n)(mutationCount) override def drop(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.Drop(this, n)(mutationCount) override def dropRight(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.DropRight(this, n)(mutationCount) - override def map[B](f: A => B): IndexedSeqView[B] = new CheckedIndexedSeqView.Map(this, f)(mutationCount) + override def map[B](f: A => B): IndexedSeqView[B]^{f} = new CheckedIndexedSeqView.Map(this, f)(mutationCount) override def reverse: IndexedSeqView[A] = new CheckedIndexedSeqView.Reverse(this)(mutationCount) override def slice(from: Int, until: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.Slice(this, from, until)(mutationCount) - override def tapEach[U](f: A => U): IndexedSeqView[A] = new CheckedIndexedSeqView.Map(this, { (a: A) => f(a); a})(mutationCount) + override def tapEach[U](f: A => U): IndexedSeqView[A]^{f} = new CheckedIndexedSeqView.Map(this, { (a: A) => f(a); a})(mutationCount) override def concat[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) override def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) diff --git a/scala2-library-cc/src/scala/collection/mutable/ArrayBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/ArrayBuilder.scala index 454527bcdebd..be7367c7f021 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ArrayBuilder.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ArrayBuilder.scala @@ -13,6 +13,7 @@ package scala.collection package mutable +import language.experimental.captureChecking import scala.reflect.ClassTag /** A builder class for arrays. @@ -57,7 +58,7 @@ sealed abstract class ArrayBuilder[T] this } - override def addAll(xs: IterableOnce[T]): this.type = { + override def addAll(xs: IterableOnce[T]^): this.type = { val k = xs.knownSize if (k > 0) { ensureSize(this.size + k) @@ -493,7 +494,7 @@ object ArrayBuilder { this } - override def addAll(xs: IterableOnce[Unit]): this.type = { + override def addAll(xs: IterableOnce[Unit]^): this.type = { size += xs.iterator.size this } diff --git a/scala2-library-cc/src/scala/collection/mutable/ArrayDeque.scala b/scala2-library-cc/src/scala/collection/mutable/ArrayDeque.scala index f164c76283bc..d72e483a7f60 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ArrayDeque.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ArrayDeque.scala @@ -18,6 +18,7 @@ import scala.annotation.nowarn import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.reflect.ClassTag +import language.experimental.captureChecking /** An implementation of a double-ended queue that internally uses a resizable circular buffer. * @@ -99,7 +100,7 @@ class ArrayDeque[A] protected ( this } - override def prependAll(elems: IterableOnce[A]): this.type = { + override def prependAll(elems: IterableOnce[A]^): this.type = { val it = elems.iterator if (it.nonEmpty) { val n = length @@ -112,8 +113,7 @@ class ArrayDeque[A] protected ( case srcLength if mustGrow(srcLength + n) => val finalLength = srcLength + n val array2 = ArrayDeque.alloc(finalLength) - @annotation.unused val copied = it.copyToArray(array2.asInstanceOf[Array[A]]) - //assert(copied == srcLength) + it.copyToArray(array2.asInstanceOf[Array[A]]) copySliceToArray(srcStart = 0, dest = array2, destStart = srcLength, maxItems = n) reset(array = array2, start = 0, end = finalLength) @@ -131,7 +131,7 @@ class ArrayDeque[A] protected ( this } - override def addAll(elems: IterableOnce[A]): this.type = { + override def addAll(elems: IterableOnce[A]^): this.type = { elems.knownSize match { case srcLength if srcLength > 0 => ensureSize(srcLength + length) @@ -177,7 +177,7 @@ class ArrayDeque[A] protected ( } } - def insertAll(idx: Int, elems: IterableOnce[A]): Unit = { + def insertAll(idx: Int, elems: IterableOnce[A]^): Unit = { requireBounds(idx, length+1) val n = length if (idx == 0) { @@ -200,8 +200,7 @@ class ArrayDeque[A] protected ( if (mustGrow(finalLength)) { val array2 = ArrayDeque.alloc(finalLength) copySliceToArray(srcStart = 0, dest = array2, destStart = 0, maxItems = idx) - @annotation.unused val copied = it.copyToArray(array2.asInstanceOf[Array[A]], idx) - //assert(copied == srcLength) + it.copyToArray(array2.asInstanceOf[Array[A]], idx) copySliceToArray(srcStart = idx, dest = array2, destStart = idx + srcLength, maxItems = n) reset(array = array2, start = 0, end = finalLength) } else if (2*idx >= n) { // Cheaper to shift the suffix right @@ -527,7 +526,7 @@ class ArrayDeque[A] protected ( @SerialVersionUID(3L) object ArrayDeque extends StrictOptimizedSeqFactory[ArrayDeque] { - def from[B](coll: collection.IterableOnce[B]): ArrayDeque[B] = { + def from[B](coll: collection.IterableOnce[B]^): ArrayDeque[B] = { val s = coll.knownSize if (s >= 0) { val array = alloc(s) diff --git a/scala2-library-cc/src/scala/collection/mutable/ArraySeq.scala b/scala2-library-cc/src/scala/collection/mutable/ArraySeq.scala index eb37c2e24f76..70762e5b340d 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ArraySeq.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ArraySeq.scala @@ -12,11 +12,14 @@ package scala.collection package mutable + import java.util.Arrays + import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl._ import scala.reflect.ClassTag import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** * A collection representing `Array[T]`. Unlike `ArrayBuffer` it is always backed by the same @@ -37,18 +40,20 @@ sealed abstract class ArraySeq[T] with IndexedSeq[T] with IndexedSeqOps[T, ArraySeq, ArraySeq[T]] with StrictOptimizedSeqOps[T, ArraySeq, ArraySeq[T]] - with Serializable { + with Serializable + with Pure { override def iterableFactory: scala.collection.SeqFactory[ArraySeq] = ArraySeq.untagged - override protected def fromSpecific(coll: scala.collection.IterableOnce[T]): ArraySeq[T] = { + override protected def fromSpecific(coll: scala.collection.IterableOnce[T]^): ArraySeq[T] = { val b = ArrayBuilder.make(elemTag).asInstanceOf[ArrayBuilder[T]] val s = coll.knownSize if(s > 0) b.sizeHint(s) b ++= coll ArraySeq.make(b.result()) } - override protected def newSpecificBuilder: Builder[T, ArraySeq[T]] = ArraySeq.newBuilder(elemTag).asInstanceOf[Builder[T, ArraySeq[T]]] + override protected def newSpecificBuilder: Builder[T, ArraySeq[T]] = + ArraySeq.newBuilder[T](elemTag.asInstanceOf[ClassTag[T]]).asInstanceOf[Builder[T, ArraySeq[T]]] override def empty: ArraySeq[T] = ArraySeq.empty(elemTag.asInstanceOf[ClassTag[T]]) /** The tag of the element type. This does not have to be equal to the element type of this ArraySeq. A primitive @@ -69,7 +74,7 @@ sealed abstract class ArraySeq[T] override protected[this] def className = "ArraySeq" /** Clones this object, including the underlying Array. */ - override def clone(): ArraySeq[T] = ArraySeq.make(array.clone()).asInstanceOf[ArraySeq[T]] + override def clone(): ArraySeq[T] = ArraySeq.make[T](array.clone().asInstanceOf[Array[T]]) override def copyToArray[B >: T](xs: Array[B], start: Int, len: Int): Int = { val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) @@ -87,7 +92,7 @@ sealed abstract class ArraySeq[T] } override def sorted[B >: T](implicit ord: Ordering[B]): ArraySeq[T] = - ArraySeq.make(array.sorted(ord.asInstanceOf[Ordering[Any]])).asInstanceOf[ArraySeq[T]] + ArraySeq.make(array.asInstanceOf[Array[T]].sorted(ord.asInstanceOf[Ordering[Any]])).asInstanceOf[ArraySeq[T]] override def sortInPlace[B >: T]()(implicit ord: Ordering[B]): this.type = { if (length > 1) scala.util.Sorting.stableSort(array.asInstanceOf[Array[B]]) @@ -105,7 +110,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => private[this] val EmptyArraySeq = new ofRef[AnyRef](new Array[AnyRef](0)) def empty[T : ClassTag]: ArraySeq[T] = EmptyArraySeq.asInstanceOf[ArraySeq[T]] - def from[A : ClassTag](it: scala.collection.IterableOnce[A]): ArraySeq[A] = make(Array.from[A](it)) + def from[A : ClassTag](it: scala.collection.IterableOnce[A]^): ArraySeq[A] = make(Array.from[A](it)) def newBuilder[A : ClassTag]: Builder[A, ArraySeq[A]] = ArrayBuilder.make[A].mapResult(make) @@ -137,7 +142,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofRef[T <: AnyRef](val array: Array[T]) extends ArraySeq[T] { - def elemTag: ClassTag[T] = ClassTag[T](array.getClass.getComponentType) + def elemTag = ClassTag[T](array.getClass.getComponentType) def length: Int = array.length def apply(index: Int): T = array(index) def update(index: Int, elem: T): Unit = { array(index) = elem } @@ -159,8 +164,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofByte(val array: Array[Byte]) extends ArraySeq[Byte] { - // Type erases to `ManifestFactory.ByteManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Byte.type = ClassTag.Byte + def elemTag = ClassTag.Byte def length: Int = array.length def apply(index: Int): Byte = array(index) def update(index: Int, elem: Byte): Unit = { array(index) = elem } @@ -179,8 +183,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofShort(val array: Array[Short]) extends ArraySeq[Short] { - // Type erases to `ManifestFactory.ShortManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Short.type = ClassTag.Short + def elemTag = ClassTag.Short def length: Int = array.length def apply(index: Int): Short = array(index) def update(index: Int, elem: Short): Unit = { array(index) = elem } @@ -199,8 +202,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofChar(val array: Array[Char]) extends ArraySeq[Char] { - // Type erases to `ManifestFactory.CharManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Char.type = ClassTag.Char + def elemTag = ClassTag.Char def length: Int = array.length def apply(index: Int): Char = array(index) def update(index: Int, elem: Char): Unit = { array(index) = elem } @@ -240,8 +242,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofInt(val array: Array[Int]) extends ArraySeq[Int] { - // Type erases to `ManifestFactory.IntManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Int.type = ClassTag.Int + def elemTag = ClassTag.Int def length: Int = array.length def apply(index: Int): Int = array(index) def update(index: Int, elem: Int): Unit = { array(index) = elem } @@ -260,8 +261,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofLong(val array: Array[Long]) extends ArraySeq[Long] { - // Type erases to `ManifestFactory.LongManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Long.type = ClassTag.Long + def elemTag = ClassTag.Long def length: Int = array.length def apply(index: Int): Long = array(index) def update(index: Int, elem: Long): Unit = { array(index) = elem } @@ -280,8 +280,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofFloat(val array: Array[Float]) extends ArraySeq[Float] { - // Type erases to `ManifestFactory.FloatManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Float.type = ClassTag.Float + def elemTag = ClassTag.Float def length: Int = array.length def apply(index: Int): Float = array(index) def update(index: Int, elem: Float): Unit = { array(index) = elem } @@ -300,8 +299,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofDouble(val array: Array[Double]) extends ArraySeq[Double] { - // Type erases to `ManifestFactory.DoubleManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Double.type = ClassTag.Double + def elemTag = ClassTag.Double def length: Int = array.length def apply(index: Int): Double = array(index) def update(index: Int, elem: Double): Unit = { array(index) = elem } @@ -320,8 +318,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofBoolean(val array: Array[Boolean]) extends ArraySeq[Boolean] { - // Type erases to `ManifestFactory.BooleanManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Boolean.type = ClassTag.Boolean + def elemTag = ClassTag.Boolean def length: Int = array.length def apply(index: Int): Boolean = array(index) def update(index: Int, elem: Boolean): Unit = { array(index) = elem } @@ -337,8 +334,7 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => @SerialVersionUID(3L) final class ofUnit(val array: Array[Unit]) extends ArraySeq[Unit] { - // Type erases to `ManifestFactory.UnitManifest`, but can't annotate that because it's not accessible - def elemTag: ClassTag.Unit.type = ClassTag.Unit + def elemTag = ClassTag.Unit def length: Int = array.length def apply(index: Int): Unit = array(index) def update(index: Int, elem: Unit): Unit = { array(index) = elem } diff --git a/scala2-library-cc/src/scala/collection/mutable/BitSet.scala b/scala2-library-cc/src/scala/collection/mutable/BitSet.scala index 89c5687189d7..dcb8a157389b 100644 --- a/scala2-library-cc/src/scala/collection/mutable/BitSet.scala +++ b/scala2-library-cc/src/scala/collection/mutable/BitSet.scala @@ -17,6 +17,7 @@ package mutable import scala.collection.immutable.Range import BitSetOps.{LogWL, MaxSize} import scala.annotation.implicitNotFound +import language.experimental.captureChecking /** * A class for mutable bitsets. @@ -47,11 +48,11 @@ class BitSet(protected[collection] final var elems: Array[Long]) def this() = this(0) - override protected def fromSpecific(coll: IterableOnce[Int]): BitSet = bitSetFactory.fromSpecific(coll) + override protected def fromSpecific(coll: IterableOnce[Int]^): BitSet = bitSetFactory.fromSpecific(coll) override protected def newSpecificBuilder: Builder[Int, BitSet] = bitSetFactory.newBuilder override def empty: BitSet = bitSetFactory.empty - def bitSetFactory: BitSet.type = BitSet + def bitSetFactory = BitSet override def unsorted: Set[Int] = this @@ -187,7 +188,7 @@ class BitSet(protected[collection] final var elems: Array[Long]) override def zip[B](that: IterableOnce[B])(implicit @implicitNotFound(collection.BitSet.zipOrdMsg) ev: Ordering[(Int, B)]): SortedSet[(Int, B)] = super.zip(that) - override def addAll(xs: IterableOnce[Int]): this.type = xs match { + override def addAll(xs: IterableOnce[Int]^): this.type = xs match { case bs: collection.BitSet => this |= bs case range: Range => @@ -260,7 +261,7 @@ class BitSet(protected[collection] final var elems: Array[Long]) super.subsetOf(other) } - override def subtractAll(xs: IterableOnce[Int]): this.type = xs match { + override def subtractAll(xs: IterableOnce[Int]^): this.type = xs match { case bs: collection.BitSet => this &~= bs case other => super.subtractAll(other) } @@ -360,7 +361,7 @@ class BitSet(protected[collection] final var elems: Array[Long]) @SerialVersionUID(3L) object BitSet extends SpecificIterableFactory[Int, BitSet] { - def fromSpecific(it: scala.collection.IterableOnce[Int]): BitSet = Growable.from(empty, it) + def fromSpecific(it: scala.collection.IterableOnce[Int]^): BitSet = Growable.from(empty, it) def empty: BitSet = new BitSet() diff --git a/scala2-library-cc/src/scala/collection/mutable/Buffer.scala b/scala2-library-cc/src/scala/collection/mutable/Buffer.scala index 847b924735ce..f9aa9cf28c72 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Buffer.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Buffer.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.annotation.nowarn +import language.experimental.captureChecking /** A `Buffer` is a growable and shrinkable `Seq`. */ @@ -48,19 +49,19 @@ trait Buffer[A] /** Appends the elements contained in a iterable object to this buffer. * @param xs the iterable object containing the elements to append. */ - @`inline` final def appendAll(xs: IterableOnce[A]): this.type = addAll(xs) + @`inline` final def appendAll(xs: IterableOnce[A]^): this.type = addAll(xs) /** Alias for `prepend` */ @`inline` final def +=: (elem: A): this.type = prepend(elem) - def prependAll(elems: IterableOnce[A]): this.type = { insertAll(0, elems); this } + def prependAll(elems: IterableOnce[A]^): this.type = { insertAll(0, elems); this } @deprecated("Use prependAll instead", "2.13.0") @`inline` final def prepend(elems: A*): this.type = prependAll(elems) /** Alias for `prependAll` */ - @inline final def ++=:(elems: IterableOnce[A]): this.type = prependAll(elems) + @inline final def ++=:(elems: IterableOnce[A]^): this.type = prependAll(elems) /** Inserts a new element at a given index into this buffer. * @@ -81,7 +82,7 @@ trait Buffer[A] * @throws IndexOutOfBoundsException if `idx` is out of bounds. */ @throws[IndexOutOfBoundsException] - def insertAll(idx: Int, elems: IterableOnce[A]): Unit + def insertAll(idx: Int, elems: IterableOnce[A]^): Unit /** Removes the element at a given index position. * @@ -103,7 +104,6 @@ trait Buffer[A] @throws[IndexOutOfBoundsException] @throws[IllegalArgumentException] def remove(idx: Int, count: Int): Unit - /** Removes a single element from this buffer, at its first occurrence. * If the buffer does not contain that element, it is unchanged. * @@ -132,7 +132,7 @@ trait Buffer[A] @deprecated("use dropRightInPlace instead", since = "2.13.4") def trimEnd(n: Int): Unit = dropRightInPlace(n) - def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type + def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A]^, replaced: Int): this.type // +=, ++=, clear inherited from Growable // Per remark of @ichoran, we should preferably not have these: @@ -180,11 +180,11 @@ trait IndexedBuffer[A] extends IndexedSeq[A] override def iterableFactory: SeqFactory[IndexedBuffer] = IndexedBuffer - def flatMapInPlace(f: A => IterableOnce[A]): this.type = { + def flatMapInPlace(f: A => IterableOnce[A]^): this.type = { // There's scope for a better implementation which copies elements in place. var i = 0 val s = size - val newElems = new Array[IterableOnce[A]](s) + val newElems = new Array[(IterableOnce[A]^{f*})](s) while (i < s) { newElems(i) = f(this(i)); i += 1 } clear() i = 0 @@ -207,7 +207,7 @@ trait IndexedBuffer[A] extends IndexedSeq[A] if (i == j) this else takeInPlace(j) } - def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type = { + def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A]^, replaced: Int): this.type = { val replaced0 = math.min(math.max(replaced, 0), length) val i = math.min(math.max(from, 0), length) var j = 0 diff --git a/scala2-library-cc/src/scala/collection/mutable/Builder.scala b/scala2-library-cc/src/scala/collection/mutable/Builder.scala index 0ecc06dff061..dd57cb75da91 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Builder.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Builder.scala @@ -12,6 +12,9 @@ package scala.collection.mutable +import language.experimental.captureChecking + + /** Base trait for collection builders. * * After calling `result()` the behavior of a Builder (which is not also a [[scala.collection.mutable.ReusableBuilder]]) @@ -20,7 +23,8 @@ package scala.collection.mutable * * @see [[scala.collection.mutable.ReusableBuilder]] for Builders which can be reused after calling `result()` */ -trait Builder[-A, +To] extends Growable[A] { self => +trait Builder[-A, +To] extends Growable[A] { + self: Builder[A, To]^ => /** Clears the contents of this builder. * After execution of this method the builder will contain no elements. @@ -51,7 +55,7 @@ trait Builder[-A, +To] extends Growable[A] { self => * @param coll the collection which serves as a hint for the result's size. * @param delta a correction to add to the `coll.size` to produce the size hint. */ - final def sizeHint(coll: scala.collection.IterableOnce[_], delta: Int = 0): Unit = { + final def sizeHint(coll: scala.collection.IterableOnce[_]^, delta: Int = 0): Unit = { val s = coll.knownSize if (s != -1) sizeHint(s + delta) } @@ -69,7 +73,7 @@ trait Builder[-A, +To] extends Growable[A] { self => * than collection's size are reduced. */ // should probably be `boundingColl: IterableOnce[_]`, but binary compatibility - final def sizeHintBounded(size: Int, boundingColl: scala.collection.Iterable[_]): Unit = { + final def sizeHintBounded(size: Int, boundingColl: scala.collection.Iterable[_]^): Unit = { val s = boundingColl.knownSize if (s != -1) { sizeHint(scala.math.min(s, size)) @@ -77,10 +81,10 @@ trait Builder[-A, +To] extends Growable[A] { self => } /** A builder resulting from this builder my mapping the result using `f`. */ - def mapResult[NewTo](f: To => NewTo): Builder[A, NewTo] = new Builder[A, NewTo] { + def mapResult[NewTo](f: To => NewTo): Builder[A, NewTo]^{this, f} = new Builder[A, NewTo] { def addOne(x: A): this.type = { self += x; this } def clear(): Unit = self.clear() - override def addAll(xs: IterableOnce[A]): this.type = { self ++= xs; this } + override def addAll(xs: IterableOnce[A]^): this.type = { self ++= xs; this } override def sizeHint(size: Int): Unit = self.sizeHint(size) def result(): NewTo = f(self.result()) override def knownSize: Int = self.knownSize diff --git a/scala2-library-cc/src/scala/collection/mutable/CheckedIndexedSeqView.scala b/scala2-library-cc/src/scala/collection/mutable/CheckedIndexedSeqView.scala index b9598904375d..152b6cc9ffc7 100644 --- a/scala2-library-cc/src/scala/collection/mutable/CheckedIndexedSeqView.scala +++ b/scala2-library-cc/src/scala/collection/mutable/CheckedIndexedSeqView.scala @@ -13,34 +13,37 @@ package scala package collection package mutable +import language.experimental.captureChecking private[mutable] trait CheckedIndexedSeqView[+A] extends IndexedSeqView[A] { + this: CheckedIndexedSeqView[A]^ => + protected val mutationCount: () => Int - override def iterator: Iterator[A] = new CheckedIndexedSeqView.CheckedIterator(this, mutationCount()) - override def reverseIterator: Iterator[A] = new CheckedIndexedSeqView.CheckedReverseIterator(this, mutationCount()) - - override def appended[B >: A](elem: B): IndexedSeqView[B] = new CheckedIndexedSeqView.Appended(this, elem)(mutationCount) - override def prepended[B >: A](elem: B): IndexedSeqView[B] = new CheckedIndexedSeqView.Prepended(elem, this)(mutationCount) - override def take(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.Take(this, n)(mutationCount) - override def takeRight(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.TakeRight(this, n)(mutationCount) - override def drop(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.Drop(this, n)(mutationCount) - override def dropRight(n: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.DropRight(this, n)(mutationCount) - override def map[B](f: A => B): IndexedSeqView[B] = new CheckedIndexedSeqView.Map(this, f)(mutationCount) - override def reverse: IndexedSeqView[A] = new CheckedIndexedSeqView.Reverse(this)(mutationCount) - override def slice(from: Int, until: Int): IndexedSeqView[A] = new CheckedIndexedSeqView.Slice(this, from, until)(mutationCount) - override def tapEach[U](f: A => U): IndexedSeqView[A] = new CheckedIndexedSeqView.Map(this, { (a: A) => f(a); a})(mutationCount) - - override def concat[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) - override def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) - override def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B] = new CheckedIndexedSeqView.Concat(prefix, this)(mutationCount) + override def iterator: Iterator[A]^{this} = new CheckedIndexedSeqView.CheckedIterator(this, mutationCount()) + override def reverseIterator: Iterator[A]^{this} = new CheckedIndexedSeqView.CheckedReverseIterator(this, mutationCount()) + + override def appended[B >: A](elem: B): IndexedSeqView[B]^{this} = new CheckedIndexedSeqView.Appended(this, elem)(mutationCount) + override def prepended[B >: A](elem: B): IndexedSeqView[B]^{this} = new CheckedIndexedSeqView.Prepended(elem, this)(mutationCount) + override def take(n: Int): IndexedSeqView[A]^{this} = new CheckedIndexedSeqView.Take(this, n)(mutationCount) + override def takeRight(n: Int): IndexedSeqView[A]^{this} = new CheckedIndexedSeqView.TakeRight(this, n)(mutationCount) + override def drop(n: Int): IndexedSeqView[A]^{this} = new CheckedIndexedSeqView.Drop(this, n)(mutationCount) + override def dropRight(n: Int): IndexedSeqView[A]^{this} = new CheckedIndexedSeqView.DropRight(this, n)(mutationCount) + override def map[B](f: A => B): IndexedSeqView[B]^{this, f} = new CheckedIndexedSeqView.Map(this, f)(mutationCount) + override def reverse: IndexedSeqView[A]^{this} = new CheckedIndexedSeqView.Reverse(this)(mutationCount) + override def slice(from: Int, until: Int): IndexedSeqView[A]^{this} = new CheckedIndexedSeqView.Slice(this, from, until)(mutationCount) + override def tapEach[U](f: A => U): IndexedSeqView[A]^{this, f} = new CheckedIndexedSeqView.Map(this, { (a: A) => f(a); a})(mutationCount) + + override def concat[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B]^{this} = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) + override def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B]^{this} = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) + override def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]): IndexedSeqView[B]^{this} = new CheckedIndexedSeqView.Concat(prefix, this)(mutationCount) } private[mutable] object CheckedIndexedSeqView { import IndexedSeqView.SomeIndexedSeqOps @SerialVersionUID(3L) - private[mutable] class CheckedIterator[A](self: IndexedSeqView[A], mutationCount: => Int) + private[mutable] class CheckedIterator[A](self: IndexedSeqView[A]^, mutationCount: => Int) extends IndexedSeqView.IndexedSeqViewIterator[A](self) { private[this] val expectedCount = mutationCount override def hasNext: Boolean = { @@ -50,7 +53,7 @@ private[mutable] object CheckedIndexedSeqView { } @SerialVersionUID(3L) - private[mutable] class CheckedReverseIterator[A](self: IndexedSeqView[A], mutationCount: => Int) + private[mutable] class CheckedReverseIterator[A](self: IndexedSeqView[A]^, mutationCount: => Int) extends IndexedSeqView.IndexedSeqViewReverseIterator[A](self) { private[this] val expectedCount = mutationCount override def hasNext: Boolean = { @@ -60,43 +63,43 @@ private[mutable] object CheckedIndexedSeqView { } @SerialVersionUID(3L) - class Id[+A](underlying: SomeIndexedSeqOps[A])(protected val mutationCount: () => Int) + class Id[+A](underlying: SomeIndexedSeqOps[A]^)(protected val mutationCount: () => Int) extends IndexedSeqView.Id(underlying) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class Appended[+A](underlying: SomeIndexedSeqOps[A], elem: A)(protected val mutationCount: () => Int) + class Appended[+A](underlying: SomeIndexedSeqOps[A]^, elem: A)(protected val mutationCount: () => Int) extends IndexedSeqView.Appended(underlying, elem) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class Prepended[+A](elem: A, underlying: SomeIndexedSeqOps[A])(protected val mutationCount: () => Int) + class Prepended[+A](elem: A, underlying: SomeIndexedSeqOps[A]^)(protected val mutationCount: () => Int) extends IndexedSeqView.Prepended(elem, underlying) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class Concat[A](prefix: SomeIndexedSeqOps[A], suffix: SomeIndexedSeqOps[A])(protected val mutationCount: () => Int) + class Concat[A](prefix: SomeIndexedSeqOps[A]^, suffix: SomeIndexedSeqOps[A]^)(protected val mutationCount: () => Int) extends IndexedSeqView.Concat[A](prefix, suffix) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class Take[A](underlying: SomeIndexedSeqOps[A], n: Int)(protected val mutationCount: () => Int) + class Take[A](underlying: SomeIndexedSeqOps[A]^, n: Int)(protected val mutationCount: () => Int) extends IndexedSeqView.Take(underlying, n) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class TakeRight[A](underlying: SomeIndexedSeqOps[A], n: Int)(protected val mutationCount: () => Int) + class TakeRight[A](underlying: SomeIndexedSeqOps[A]^, n: Int)(protected val mutationCount: () => Int) extends IndexedSeqView.TakeRight(underlying, n) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class Drop[A](underlying: SomeIndexedSeqOps[A], n: Int)(protected val mutationCount: () => Int) + class Drop[A](underlying: SomeIndexedSeqOps[A]^, n: Int)(protected val mutationCount: () => Int) extends IndexedSeqView.Drop[A](underlying, n) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class DropRight[A](underlying: SomeIndexedSeqOps[A], n: Int)(protected val mutationCount: () => Int) + class DropRight[A](underlying: SomeIndexedSeqOps[A]^, n: Int)(protected val mutationCount: () => Int) extends IndexedSeqView.DropRight[A](underlying, n) with CheckedIndexedSeqView[A] @SerialVersionUID(3L) - class Map[A, B](underlying: SomeIndexedSeqOps[A], f: A => B)(protected val mutationCount: () => Int) + class Map[A, B](underlying: SomeIndexedSeqOps[A]^, f: A => B)(protected val mutationCount: () => Int) extends IndexedSeqView.Map(underlying, f) with CheckedIndexedSeqView[B] @SerialVersionUID(3L) - class Reverse[A](underlying: SomeIndexedSeqOps[A])(protected val mutationCount: () => Int) + class Reverse[A](underlying: SomeIndexedSeqOps[A]^)(protected val mutationCount: () => Int) extends IndexedSeqView.Reverse[A](underlying) with CheckedIndexedSeqView[A] { override def reverse: IndexedSeqView[A] = underlying match { case x: IndexedSeqView[A] => x @@ -105,7 +108,7 @@ private[mutable] object CheckedIndexedSeqView { } @SerialVersionUID(3L) - class Slice[A](underlying: SomeIndexedSeqOps[A], from: Int, until: Int)(protected val mutationCount: () => Int) + class Slice[A](underlying: SomeIndexedSeqOps[A]^, from: Int, until: Int)(protected val mutationCount: () => Int) extends AbstractIndexedSeqView[A] with CheckedIndexedSeqView[A] { protected val lo = from max 0 protected val hi = (until max 0) min underlying.length diff --git a/scala2-library-cc/src/scala/collection/mutable/Cloneable.scala b/scala2-library-cc/src/scala/collection/mutable/Cloneable.scala index 940ecf3549ad..39149e98cbf0 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Cloneable.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Cloneable.scala @@ -11,7 +11,7 @@ */ package scala.collection.mutable - +import language.experimental.captureChecking /** A trait for cloneable collections. * diff --git a/scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala index 8542b5b56a01..ff3bab1dd818 100644 --- a/scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala @@ -18,6 +18,7 @@ import scala.annotation.{implicitNotFound, tailrec, unused} import scala.annotation.unchecked.uncheckedVariance import scala.collection.generic.DefaultSerializationProxy import scala.runtime.Statics +import language.experimental.captureChecking /** This class implements mutable maps using a hashtable with red-black trees in the buckets for good * worst-case performance on hash collisions. An `Ordering` is required for the element type. Equality @@ -63,7 +64,7 @@ final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double @`inline` private[this] final def index(hash: Int) = hash & (table.length - 1) - override protected def fromSpecific(coll: IterableOnce[(K, V)] @uncheckedVariance): CollisionProofHashMap[K, V] @uncheckedVariance = CollisionProofHashMap.from(coll) + override protected def fromSpecific(coll: (IterableOnce[(K, V)]^) @uncheckedVariance): CollisionProofHashMap[K, V] @uncheckedVariance = CollisionProofHashMap.from(coll) override protected def newSpecificBuilder: Builder[(K, V), CollisionProofHashMap[K, V]] @uncheckedVariance = CollisionProofHashMap.newBuilder[K, V] override def empty: CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V] @@ -173,7 +174,7 @@ final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double } } - override def addAll(xs: IterableOnce[(K, V)]): this.type = { + override def addAll(xs: IterableOnce[(K, V)]^): this.type = { val k = xs.knownSize if(k > 0) sizeHint(contentSize + k) super.addAll(xs) @@ -442,13 +443,13 @@ final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double (implicit @implicitNotFound(CollisionProofHashMap.ordMsg) ordering: Ordering[K2]): CollisionProofHashMap[K2, V2] = sortedMapFactory.from(new View.Collect(this, pf)) - override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]): CollisionProofHashMap[K, V2] = sortedMapFactory.from(suffix match { + override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]^): CollisionProofHashMap[K, V2] = sortedMapFactory.from(suffix match { case it: Iterable[(K, V2)] => new View.Concat(this, it) case _ => iterator.concat(suffix.iterator) }) /** Alias for `concat` */ - @`inline` override final def ++ [V2 >: V](xs: IterableOnce[(K, V2)]): CollisionProofHashMap[K, V2] = concat(xs) + @`inline` override final def ++ [V2 >: V](xs: IterableOnce[(K, V2)]^): CollisionProofHashMap[K, V2] = concat(xs) @deprecated("Consider requiring an immutable Map or fall back to Map.concat", "2.13.0") override def + [V1 >: V](kv: (K, V1)): CollisionProofHashMap[K, V1] = @@ -743,7 +744,7 @@ final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { private[collection] final val ordMsg = "No implicit Ordering[${K2}] found to build a CollisionProofHashMap[${K2}, ${V2}]. You may want to upcast to a Map[${K}, ${V}] first by calling `unsorted`." - def from[K : Ordering, V](it: scala.collection.IterableOnce[(K, V)]): CollisionProofHashMap[K, V] = { + def from[K : Ordering, V](it: scala.collection.IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new CollisionProofHashMap[K, V](cap, defaultLoadFactor) ++= it @@ -766,7 +767,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { @SerialVersionUID(3L) private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double, val ordering: Ordering[K]) extends Factory[(K, V), CollisionProofHashMap[K, V]] with Serializable { - def fromSpecific(it: IterableOnce[(K, V)]): CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V](tableLength, loadFactor)(ordering) ++= it + def fromSpecific(it: IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V](tableLength, loadFactor)(ordering) ++= it def newBuilder: Builder[(K, V), CollisionProofHashMap[K, V]] = CollisionProofHashMap.newBuilder(tableLength, loadFactor)(ordering) } diff --git a/scala2-library-cc/src/scala/collection/mutable/Growable.scala b/scala2-library-cc/src/scala/collection/mutable/Growable.scala index 914742b9013a..3b5eabac37bf 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Growable.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Growable.scala @@ -14,6 +14,8 @@ package scala package collection package mutable +import language.experimental.captureChecking + /** This trait forms part of collections that can be augmented * using a `+=` operator and that can be cleared of all elements using * a `clear` method. @@ -54,7 +56,7 @@ trait Growable[-A] extends Clearable { * @param xs the IterableOnce producing the elements to $add. * @return the $coll itself. */ - def addAll(xs: IterableOnce[A]): this.type = { + def addAll(xs: IterableOnce[A]^): this.type = { if (xs.asInstanceOf[AnyRef] eq this) addAll(Buffer.from(xs)) // avoid mutating under our own iterator else { val it = xs.iterator @@ -66,7 +68,7 @@ trait Growable[-A] extends Clearable { } /** Alias for `addAll` */ - @`inline` final def ++= (xs: IterableOnce[A]): this.type = addAll(xs) + @`inline` final def ++= (xs: IterableOnce[A]^): this.type = addAll(xs) /** @return The number of elements in the collection under construction, if it can be cheaply computed, * -1 otherwise. The default implementation always returns -1. @@ -83,7 +85,7 @@ object Growable { * @tparam A Element type * @return The filled instance */ - def from[A](empty: Growable[A], it: collection.IterableOnce[A]): empty.type = empty ++= it + def from[A](empty: Growable[A], it: collection.IterableOnce[A]^): empty.type = empty ++= it } diff --git a/scala2-library-cc/src/scala/collection/mutable/GrowableBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/GrowableBuilder.scala index 7e945dffb99e..4d6f989e6f3d 100644 --- a/scala2-library-cc/src/scala/collection/mutable/GrowableBuilder.scala +++ b/scala2-library-cc/src/scala/collection/mutable/GrowableBuilder.scala @@ -12,7 +12,7 @@ package scala package collection.mutable - +import language.experimental.captureChecking /** The canonical builder for collections that are growable, i.e. that support an * efficient `+=` method which adds an element to the collection. @@ -31,7 +31,7 @@ class GrowableBuilder[Elem, To <: Growable[Elem]](protected val elems: To) def addOne(elem: Elem): this.type = { elems += elem; this } - override def addAll(xs: IterableOnce[Elem]): this.type = { elems.addAll(xs); this } + override def addAll(xs: IterableOnce[Elem]^): this.type = { elems.addAll(xs); this } override def knownSize: Int = elems.knownSize } diff --git a/scala2-library-cc/src/scala/collection/mutable/HashMap.scala b/scala2-library-cc/src/scala/collection/mutable/HashMap.scala index 7ad3cf3869e8..89a9f3f186f7 100644 --- a/scala2-library-cc/src/scala/collection/mutable/HashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/HashMap.scala @@ -17,6 +17,7 @@ import scala.annotation.{nowarn, tailrec} import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializationProxy import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** This class implements mutable maps using a hashtable. * @@ -94,7 +95,7 @@ class HashMap[K, V](initialCapacity: Int, loadFactor: Double) if(target > table.length) growTable(target) } - override def addAll(xs: IterableOnce[(K, V)]): this.type = { + override def addAll(xs: IterableOnce[(K, V)]^): this.type = { sizeHint(xs.knownSize) xs match { @@ -182,7 +183,7 @@ class HashMap[K, V](initialCapacity: Int, loadFactor: Double) } } - override def subtractAll(xs: IterableOnce[K]): this.type = { + override def subtractAll(xs: IterableOnce[K]^): this.type = { if (size == 0) { return this } @@ -598,7 +599,7 @@ object HashMap extends MapFactory[HashMap] { def empty[K, V]: HashMap[K, V] = new HashMap[K, V] - def from[K, V](it: collection.IterableOnce[(K, V)]): HashMap[K, V] = { + def from[K, V](it: collection.IterableOnce[(K, V)]^): HashMap[K, V] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new HashMap[K, V](cap, defaultLoadFactor).addAll(it) @@ -619,7 +620,7 @@ object HashMap extends MapFactory[HashMap] { @SerialVersionUID(3L) private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double) extends Factory[(K, V), HashMap[K, V]] with Serializable { - def fromSpecific(it: IterableOnce[(K, V)]): HashMap[K, V] = new HashMap[K, V](tableLength, loadFactor).addAll(it) + def fromSpecific(it: IterableOnce[(K, V)]^): HashMap[K, V] = new HashMap[K, V](tableLength, loadFactor).addAll(it) def newBuilder: Builder[(K, V), HashMap[K, V]] = HashMap.newBuilder(tableLength, loadFactor) } diff --git a/scala2-library-cc/src/scala/collection/mutable/HashSet.scala b/scala2-library-cc/src/scala/collection/mutable/HashSet.scala index 425721a41626..487abc74bb82 100644 --- a/scala2-library-cc/src/scala/collection/mutable/HashSet.scala +++ b/scala2-library-cc/src/scala/collection/mutable/HashSet.scala @@ -17,6 +17,7 @@ import scala.annotation.tailrec import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializationProxy import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** This class implements mutable sets using a hashtable. * @@ -90,7 +91,7 @@ final class HashSet[A](initialCapacity: Int, loadFactor: Double) addElem(elem, computeHash(elem)) } - override def addAll(xs: IterableOnce[A]): this.type = { + override def addAll(xs: IterableOnce[A]^): this.type = { sizeHint(xs.knownSize) xs match { case hs: immutable.HashSet[A] => @@ -114,7 +115,7 @@ final class HashSet[A](initialCapacity: Int, loadFactor: Double) } } - override def subtractAll(xs: IterableOnce[A]): this.type = { + override def subtractAll(xs: IterableOnce[A]^): this.type = { if (size == 0) { return this } @@ -406,7 +407,7 @@ final class HashSet[A](initialCapacity: Int, loadFactor: Double) @SerialVersionUID(3L) object HashSet extends IterableFactory[HashSet] { - def from[B](it: scala.collection.IterableOnce[B]): HashSet[B] = { + def from[B](it: scala.collection.IterableOnce[B]^): HashSet[B] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new HashSet[B](cap, defaultLoadFactor) ++= it @@ -429,7 +430,7 @@ object HashSet extends IterableFactory[HashSet] { @SerialVersionUID(3L) private final class DeserializationFactory[A](val tableLength: Int, val loadFactor: Double) extends Factory[A, HashSet[A]] with Serializable { - def fromSpecific(it: IterableOnce[A]): HashSet[A] = new HashSet[A](tableLength, loadFactor) ++= it + def fromSpecific(it: IterableOnce[A]^): HashSet[A] = new HashSet[A](tableLength, loadFactor) ++= it def newBuilder: Builder[A, HashSet[A]] = HashSet.newBuilder(tableLength, loadFactor) } diff --git a/scala2-library-cc/src/scala/collection/mutable/HashTable.scala b/scala2-library-cc/src/scala/collection/mutable/HashTable.scala index 4153bd532163..461df6cea22c 100644 --- a/scala2-library-cc/src/scala/collection/mutable/HashTable.scala +++ b/scala2-library-cc/src/scala/collection/mutable/HashTable.scala @@ -19,6 +19,7 @@ import java.lang.Integer.{numberOfLeadingZeros, rotateRight} import scala.util.hashing.byteswap32 import java.lang.Integer +import language.experimental.captureChecking /** This class can be used to construct data structures that are based * on hashtables. Class `HashTable[A]` implements a hashtable diff --git a/scala2-library-cc/src/scala/collection/mutable/ImmutableBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/ImmutableBuilder.scala index c801f073fb0d..1af98162e9f3 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ImmutableBuilder.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ImmutableBuilder.scala @@ -13,6 +13,7 @@ package scala package collection package mutable +import language.experimental.captureChecking /** diff --git a/scala2-library-cc/src/scala/collection/mutable/IndexedSeq.scala b/scala2-library-cc/src/scala/collection/mutable/IndexedSeq.scala index 24d54905de22..022970b4c56f 100644 --- a/scala2-library-cc/src/scala/collection/mutable/IndexedSeq.scala +++ b/scala2-library-cc/src/scala/collection/mutable/IndexedSeq.scala @@ -12,6 +12,7 @@ package scala.collection package mutable +import language.experimental.captureChecking trait IndexedSeq[T] extends Seq[T] with scala.collection.IndexedSeq[T] diff --git a/scala2-library-cc/src/scala/collection/mutable/Iterable.scala b/scala2-library-cc/src/scala/collection/mutable/Iterable.scala index d05aeed88044..bf286157b376 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Iterable.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Iterable.scala @@ -13,11 +13,13 @@ package scala.collection.mutable import scala.collection.{IterableFactory, IterableFactoryDefaults} +import language.experimental.captureChecking trait Iterable[A] extends collection.Iterable[A] with collection.IterableOps[A, Iterable, Iterable[A]] with IterableFactoryDefaults[A, Iterable] { + this: Iterable[A]^ => override def iterableFactory: IterableFactory[Iterable] = Iterable } @@ -31,4 +33,5 @@ trait Iterable[A] object Iterable extends IterableFactory.Delegate[Iterable](ArrayBuffer) /** Explicit instantiation of the `Iterable` trait to reduce class file size in subclasses. */ -abstract class AbstractIterable[A] extends scala.collection.AbstractIterable[A] with Iterable[A] +abstract class AbstractIterable[A] extends scala.collection.AbstractIterable[A] with Iterable[A]: + this: AbstractIterable[A]^ => diff --git a/scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala index 83add59696fa..e3fc9d6aefd6 100644 --- a/scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala @@ -17,6 +17,7 @@ package mutable import scala.annotation.{nowarn, tailrec} import scala.collection.generic.DefaultSerializable import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** This class implements mutable maps using a hashtable. @@ -478,14 +479,14 @@ object LinkedHashMap extends MapFactory[LinkedHashMap] { def empty[K, V] = new LinkedHashMap[K, V] - def from[K, V](it: collection.IterableOnce[(K, V)]) = { + def from[K, V](it: collection.IterableOnce[(K, V)]^) = { val newlhm = empty[K, V] newlhm.sizeHint(it.knownSize) newlhm.addAll(it) newlhm } - def newBuilder[K, V]: GrowableBuilder[(K, V), LinkedHashMap[K, V]] = new GrowableBuilder(empty[K, V]) + def newBuilder[K, V] = new GrowableBuilder(empty[K, V]) /** Class for the linked hash map entry, used internally. */ diff --git a/scala2-library-cc/src/scala/collection/mutable/LinkedHashSet.scala b/scala2-library-cc/src/scala/collection/mutable/LinkedHashSet.scala index 2a419efccfbc..b9db31651ede 100644 --- a/scala2-library-cc/src/scala/collection/mutable/LinkedHashSet.scala +++ b/scala2-library-cc/src/scala/collection/mutable/LinkedHashSet.scala @@ -17,6 +17,7 @@ package mutable import scala.annotation.{nowarn, tailrec} import scala.collection.generic.DefaultSerializable import scala.util.hashing.MurmurHash3 +import language.experimental.captureChecking /** This class implements mutable sets using a hashtable. * The iterator and all traversal methods of this class visit elements in the order they were inserted. @@ -316,14 +317,14 @@ object LinkedHashSet extends IterableFactory[LinkedHashSet] { override def empty[A]: LinkedHashSet[A] = new LinkedHashSet[A] - def from[E](it: collection.IterableOnce[E]) = { + def from[E](it: collection.IterableOnce[E]^) = { val newlhs = empty[E] newlhs.sizeHint(it.knownSize) newlhs.addAll(it) newlhs } - def newBuilder[A]: GrowableBuilder[A, LinkedHashSet[A]] = new GrowableBuilder(empty[A]) + def newBuilder[A] = new GrowableBuilder(empty[A]) /** Class for the linked hash set entry, used internally. */ diff --git a/scala2-library-cc/src/scala/collection/mutable/ListBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/ListBuffer.scala index 7ef391dc4079..570c815644ee 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ListBuffer.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ListBuffer.scala @@ -19,6 +19,7 @@ import java.lang.{IllegalArgumentException, IndexOutOfBoundsException} import scala.collection.generic.DefaultSerializable import scala.runtime.Statics.releaseFence +import language.experimental.captureChecking /** A `Buffer` implementation backed by a list. It provides constant time * prepend and append. Most other operations are linear. @@ -46,7 +47,7 @@ class ListBuffer[A] @transient private[this] var mutationCount: Int = 0 private var first: List[A] = Nil - private var last0: ::[A] = null // last element (`last0` just because the name `last` is already taken) + private var last0: ::[A] = null private[this] var aliased = false private[this] var len = 0 @@ -121,7 +122,7 @@ class ListBuffer[A] } // MUST only be called on fresh instances - private def freshFrom(xs: IterableOnce[A]): this.type = { + private def freshFrom(xs: IterableOnce[A]^): this.type = { val it = xs.iterator if (it.hasNext) { var len = 1 @@ -140,7 +141,7 @@ class ListBuffer[A] this } - override final def addAll(xs: IterableOnce[A]): this.type = { + override final def addAll(xs: IterableOnce[A]^): this.type = { val it = xs.iterator if (it.hasNext) { val fresh = new ListBuffer[A].freshFrom(it) @@ -244,12 +245,11 @@ class ListBuffer[A] val follow = getNext(prev) if (prev eq null) first = fresh.first else prev.next = fresh.first fresh.last0.next = follow - if (follow.isEmpty) last0 = fresh.last0 len += fresh.length } } - def insertAll(idx: Int, elems: IterableOnce[A]): Unit = { + def insertAll(idx: Int, elems: IterableOnce[A]^): Unit = { if (idx < 0 || idx > len) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${len-1})") val it = elems.iterator if (it.hasNext) { @@ -306,7 +306,7 @@ class ListBuffer[A] this } - def flatMapInPlace(f: A => IterableOnce[A]): this.type = { + def flatMapInPlace(f: A => IterableOnce[A]^): this.type = { mutationCount += 1 var src = first var dst: List[A] = null @@ -346,7 +346,7 @@ class ListBuffer[A] this } - def patchInPlace(from: Int, patch: collection.IterableOnce[A], replaced: Int): this.type = { + def patchInPlace(from: Int, patch: collection.IterableOnce[A]^, replaced: Int): this.type = { val _len = len val _from = math.max(from, 0) // normalized val _replaced = math.max(replaced, 0) // normalized @@ -396,7 +396,7 @@ class ListBuffer[A] @SerialVersionUID(3L) object ListBuffer extends StrictOptimizedSeqFactory[ListBuffer] { - def from[A](coll: collection.IterableOnce[A]): ListBuffer[A] = new ListBuffer[A].freshFrom(coll) + def from[A](coll: collection.IterableOnce[A]^): ListBuffer[A] = new ListBuffer[A].freshFrom(coll) def newBuilder[A]: Builder[A, ListBuffer[A]] = new GrowableBuilder(empty[A]) diff --git a/scala2-library-cc/src/scala/collection/mutable/ListMap.scala b/scala2-library-cc/src/scala/collection/mutable/ListMap.scala index 7cc5aa227757..26e904e271a1 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ListMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ListMap.scala @@ -16,6 +16,7 @@ package mutable import scala.annotation.tailrec import scala.collection.generic.DefaultSerializable import scala.collection.immutable.List +import language.experimental.captureChecking /** A simple mutable map backed by a list, so it preserves insertion order. * @@ -77,6 +78,6 @@ class ListMap[K, V] @deprecated("Use an immutable.ListMap assigned to a var instead of mutable.ListMap", "2.13.0") object ListMap extends MapFactory[ListMap] { def empty[K, V]: ListMap[K, V] = new ListMap[K, V] - def from[K, V](it: IterableOnce[(K, V)]): ListMap[K,V] = Growable.from(empty[K, V], it) + def from[K, V](it: IterableOnce[(K, V)]^): ListMap[K,V] = Growable.from(empty[K, V], it) def newBuilder[K, V]: Builder[(K, V), ListMap[K,V]] = new GrowableBuilder(empty[K, V]) } diff --git a/scala2-library-cc/src/scala/collection/mutable/LongMap.scala b/scala2-library-cc/src/scala/collection/mutable/LongMap.scala index 615435b69701..5ac4757a42eb 100644 --- a/scala2-library-cc/src/scala/collection/mutable/LongMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/LongMap.scala @@ -15,6 +15,7 @@ package mutable import scala.collection.generic.DefaultSerializationProxy import scala.language.implicitConversions +import language.experimental.captureChecking /** This class implements mutable maps with `Long` keys based on a hash table with open addressing. * @@ -36,7 +37,7 @@ import scala.language.implicitConversions * rapidly as 2^30 is approached. * */ -final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBufferSize: Int, initBlank: Boolean) +final class LongMap[V] private[collection] (defaultEntry: Long -> V, initialBufferSize: Int, initBlank: Boolean) extends AbstractMap[Long, V] with MapOps[Long, V, Map, LongMap[V]] with StrictOptimizedIterableOps[(Long, V), Iterable, LongMap[V]] @@ -46,7 +47,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff def this() = this(LongMap.exceptionDefault, 16, true) // TODO: override clear() with an optimization more tailored for efficiency. - override protected def fromSpecific(coll: scala.collection.IterableOnce[(Long, V)]): LongMap[V] = { + override protected def fromSpecific(coll: scala.collection.IterableOnce[(Long, V)]^): LongMap[V] = { //TODO should this be the default implementation of this method in StrictOptimizedIterableOps? val b = newSpecificBuilder b.sizeHint(coll) @@ -56,7 +57,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff override protected def newSpecificBuilder: Builder[(Long, V),LongMap[V]] = new GrowableBuilder(LongMap.empty[V]) /** Creates a new `LongMap` that returns default values according to a supplied key-value mapping. */ - def this(defaultEntry: Long => V) = this(defaultEntry, 16, true) + def this(defaultEntry: Long -> V) = this(defaultEntry, 16, true) /** Creates a new `LongMap` with an initial buffer of specified size. * @@ -66,7 +67,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff def this(initialBufferSize: Int) = this(LongMap.exceptionDefault, initialBufferSize, true) /** Creates a new `LongMap` with specified default values and initial buffer size. */ - def this(defaultEntry: Long => V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, true) + def this(defaultEntry: Long -> V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, true) private[this] var mask = 0 private[this] var extraKeys: Int = 0 @@ -473,13 +474,13 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff if(elems.isEmpty) m else m.concat(elems) } - override def concat[V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]): LongMap[V1] = { + override def concat[V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = { val lm = clone().asInstanceOf[LongMap[V1]] xs.iterator.foreach(kv => lm += kv) lm } - override def ++ [V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]): LongMap[V1] = concat(xs) + override def ++ [V1 >: V](xs: scala.collection.IterableOnce[(Long, V1)]^): LongMap[V1] = concat(xs) @deprecated("Use m.clone().addOne(k,v) instead of m.updated(k, v)", "2.13.0") override def updated[V1 >: V](key: Long, value: V1): LongMap[V1] = @@ -580,7 +581,7 @@ object LongMap { private final val VacantBit = 0x40000000 private final val MissVacant = 0xC0000000 - private val exceptionDefault: Long => Nothing = (k: Long) => throw new NoSuchElementException(k.toString) + private val exceptionDefault: Long -> Nothing = (k: Long) => throw new NoSuchElementException(k.toString) /** A builder for instances of `LongMap`. * @@ -600,7 +601,7 @@ object LongMap { /** Creates a new `LongMap` with zero or more key/value pairs. */ def apply[V](elems: (Long, V)*): LongMap[V] = buildFromIterableOnce(elems) - private def buildFromIterableOnce[V](elems: IterableOnce[(Long, V)]): LongMap[V] = { + private def buildFromIterableOnce[V](elems: IterableOnce[(Long, V)]^): LongMap[V] = { var sz = elems.knownSize if(sz < 0) sz = 4 val lm = new LongMap[V](sz * 2) @@ -613,7 +614,7 @@ object LongMap { def empty[V]: LongMap[V] = new LongMap[V] /** Creates a new empty `LongMap` with the supplied default */ - def withDefault[V](default: Long => V): LongMap[V] = new LongMap[V](default) + def withDefault[V](default: Long -> V): LongMap[V] = new LongMap[V](default) /** Creates a new `LongMap` from an existing source collection. A source collection * which is already a `LongMap` gets cloned. @@ -622,7 +623,7 @@ object LongMap { * @tparam A the type of the collection’s elements * @return a new `LongMap` with the elements of `source` */ - def from[V](source: IterableOnce[(Long, V)]): LongMap[V] = source match { + def from[V](source: IterableOnce[(Long, V)]^): LongMap[V] = source match { case source: LongMap[_] => source.clone().asInstanceOf[LongMap[V]] case _ => buildFromIterableOnce(source) } @@ -658,14 +659,14 @@ object LongMap { @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(Long, AnyRef), LongMap[AnyRef]] with Serializable { - def fromSpecific(it: IterableOnce[(Long, AnyRef)]): LongMap[AnyRef] = LongMap.from[AnyRef](it) + def fromSpecific(it: IterableOnce[(Long, AnyRef)]^): LongMap[AnyRef] = LongMap.from[AnyRef](it) def newBuilder: Builder[(Long, AnyRef), LongMap[AnyRef]] = LongMap.newBuilder[AnyRef] } implicit def toBuildFrom[V](factory: LongMap.type): BuildFrom[Any, (Long, V), LongMap[V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (Long, V), LongMap[V]]] private object ToBuildFrom extends BuildFrom[Any, (Long, AnyRef), LongMap[AnyRef]] { - def fromSpecific(from: Any)(it: IterableOnce[(Long, AnyRef)]) = LongMap.from(it) - def newBuilder(from: Any): ReusableBuilder[(Long, AnyRef), LongMap[AnyRef]] = LongMap.newBuilder[AnyRef] + def fromSpecific(from: Any)(it: IterableOnce[(Long, AnyRef)]^) = LongMap.from(it) + def newBuilder(from: Any) = LongMap.newBuilder[AnyRef] } implicit def iterableFactory[V]: Factory[(Long, V), LongMap[V]] = toFactory(this) diff --git a/scala2-library-cc/src/scala/collection/mutable/Map.scala b/scala2-library-cc/src/scala/collection/mutable/Map.scala index 610dc01029cc..dab64ddb1f58 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Map.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Map.scala @@ -14,6 +14,8 @@ package scala package collection package mutable +import language.experimental.captureChecking + /** Base type of mutable Maps */ trait Map[K, V] extends Iterable[(K, V)] @@ -44,7 +46,7 @@ trait Map[K, V] * @param d the function mapping keys to values, used for non-present keys * @return a wrapper of the map with a default value */ - def withDefault(d: K => V): Map[K, V] = new Map.WithDefault[K, V](this, d) + def withDefault(d: K -> V): Map[K, V] = new Map.WithDefault[K, V](this, d) /** The same map with a given default value. * Note: The default is only used for `apply`. Other methods like `get`, `contains`, `iterator`, `keys`, etc. @@ -68,7 +70,8 @@ trait MapOps[K, V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C]] with Cloneable[C] with Builder[(K, V), C] with Growable[(K, V)] - with Shrinkable[K] { + with Shrinkable[K] + with Pure { def result(): C = coll @@ -231,7 +234,7 @@ trait MapOps[K, V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C]] object Map extends MapFactory.Delegate[Map](HashMap) { @SerialVersionUID(3L) - class WithDefault[K, V](val underlying: Map[K, V], val defaultValue: K => V) + class WithDefault[K, V](val underlying: Map[K, V], val defaultValue: K -> V) extends AbstractMap[K, V] with MapOps[K, V, Map, WithDefault[K, V]] with Serializable { @@ -250,12 +253,12 @@ object Map extends MapFactory.Delegate[Map](HashMap) { def addOne(elem: (K, V)): WithDefault.this.type = { underlying.addOne(elem); this } - override def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]): Map[K, V2] = + override def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]^): Map[K, V2] = underlying.concat(suffix).withDefault(defaultValue) override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) - override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)]): WithDefault[K, V] = + override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)]^): WithDefault[K, V] = new WithDefault[K, V](mapFactory.from(coll), defaultValue) override protected def newSpecificBuilder: Builder[(K, V), WithDefault[K, V]] = diff --git a/scala2-library-cc/src/scala/collection/mutable/MultiMap.scala b/scala2-library-cc/src/scala/collection/mutable/MultiMap.scala index 13d7c35e0165..0b250a5548ef 100644 --- a/scala2-library-cc/src/scala/collection/mutable/MultiMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/MultiMap.scala @@ -12,6 +12,7 @@ package scala.collection.mutable +import language.experimental.captureChecking /** A trait for mutable maps with multiple values assigned to a key. * diff --git a/scala2-library-cc/src/scala/collection/mutable/MutationTracker.scala b/scala2-library-cc/src/scala/collection/mutable/MutationTracker.scala index e98536d0dad5..3e9b16540031 100644 --- a/scala2-library-cc/src/scala/collection/mutable/MutationTracker.scala +++ b/scala2-library-cc/src/scala/collection/mutable/MutationTracker.scala @@ -15,6 +15,7 @@ package collection package mutable import java.util.ConcurrentModificationException +import language.experimental.captureChecking /** * Utilities to check that mutations to a client that tracks @@ -66,7 +67,7 @@ private object MutationTracker { * @param mutationCount a by-name provider of the current mutation count * @tparam A the type of the iterator's elements */ - final class CheckedIterator[A](underlying: Iterator[A], mutationCount: => Int) extends AbstractIterator[A] { + final class CheckedIterator[A](underlying: Iterator[A]^, mutationCount: => Int) extends AbstractIterator[A] { private[this] val expectedCount = mutationCount def hasNext: Boolean = { diff --git a/scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala index 22e99d4650d1..d29be3ffea5e 100644 --- a/scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala @@ -16,6 +16,7 @@ package mutable import java.lang.Integer.numberOfLeadingZeros import java.util.ConcurrentModificationException import scala.collection.generic.DefaultSerializable +import language.experimental.captureChecking /** * @define Coll `OpenHashMap` @@ -26,7 +27,7 @@ import scala.collection.generic.DefaultSerializable object OpenHashMap extends MapFactory[OpenHashMap] { def empty[K, V] = new OpenHashMap[K, V] - def from[K, V](it: IterableOnce[(K, V)]): OpenHashMap[K,V] = empty ++= it + def from[K, V](it: IterableOnce[(K, V)]^): OpenHashMap[K,V] = empty ++= it def newBuilder[K, V]: Builder[(K, V), OpenHashMap[K,V]] = new GrowableBuilder[(K, V), OpenHashMap[K, V]](empty) diff --git a/scala2-library-cc/src/scala/collection/mutable/PriorityQueue.scala b/scala2-library-cc/src/scala/collection/mutable/PriorityQueue.scala index c15d182a0120..ec923b641a71 100644 --- a/scala2-library-cc/src/scala/collection/mutable/PriorityQueue.scala +++ b/scala2-library-cc/src/scala/collection/mutable/PriorityQueue.scala @@ -15,6 +15,7 @@ package mutable import scala.collection.generic.DefaultSerializationProxy import scala.math.Ordering +import language.experimental.captureChecking /** A heap-based priority queue. * @@ -99,18 +100,14 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) private val resarr = new ResizableArrayAccess[A] - // we do not use array(0) - // storing the root of the heap at array(1) simplifies the calculations for - // parent and child indices: for a given index k, the parent of k is k / 2, - // the left child is k * 2, and the right child is k * 2 + 1 - resarr.p_size0 += 1 + resarr.p_size0 += 1 // we do not use array(0) TODO: explain -- what is the first element even for? def length: Int = resarr.length - 1 // adjust length accordingly override def size: Int = length override def knownSize: Int = length override def isEmpty: Boolean = resarr.p_size0 < 2 // not eligible for EvidenceIterableFactoryDefaults since C != CC[A] (PriorityQueue[A] != Iterable[A]) - override protected def fromSpecific(coll: scala.collection.IterableOnce[A]): PriorityQueue[A] = PriorityQueue.from(coll) + override protected def fromSpecific(coll: scala.collection.IterableOnce[A]^): PriorityQueue[A] = PriorityQueue.from(coll) override protected def newSpecificBuilder: Builder[A, PriorityQueue[A]] = PriorityQueue.newBuilder override def empty: PriorityQueue[A] = PriorityQueue.empty @@ -165,7 +162,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) this } - override def addAll(xs: IterableOnce[A]): this.type = { + override def addAll(xs: IterableOnce[A]^): this.type = { val from = resarr.p_size0 for (x <- xs.iterator) unsafeAdd(x) heapify(from) @@ -398,7 +395,7 @@ object PriorityQueue extends SortedIterableFactory[PriorityQueue] { def empty[A : Ordering]: PriorityQueue[A] = new PriorityQueue[A] - def from[E : Ordering](it: IterableOnce[E]): PriorityQueue[E] = { + def from[E : Ordering](it: IterableOnce[E]^): PriorityQueue[E] = { val b = newBuilder[E] b ++= it b.result() diff --git a/scala2-library-cc/src/scala/collection/mutable/Queue.scala b/scala2-library-cc/src/scala/collection/mutable/Queue.scala index 18cce0bd3852..884fbab798a5 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Queue.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Queue.scala @@ -15,6 +15,7 @@ package mutable import scala.annotation.nowarn import scala.collection.generic.DefaultSerializable +import language.experimental.captureChecking /** `Queue` objects implement data structures that allow to @@ -129,7 +130,7 @@ class Queue[A] protected (array: Array[AnyRef], start: Int, end: Int) @SerialVersionUID(3L) object Queue extends StrictOptimizedSeqFactory[Queue] { - def from[A](source: IterableOnce[A]): Queue[A] = empty ++= source + def from[A](source: IterableOnce[A]^): Queue[A] = empty ++= source def empty[A]: Queue[A] = new Queue diff --git a/scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala b/scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala index 3ac0e1a1f797..f808a4257eef 100644 --- a/scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala +++ b/scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala @@ -16,6 +16,7 @@ package collection.mutable import scala.annotation.tailrec import collection.{AbstractIterator, Iterator} import java.lang.String +import language.experimental.captureChecking /** * An object containing the red-black tree implementation used by mutable `TreeMaps`. diff --git a/scala2-library-cc/src/scala/collection/mutable/ReusableBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/ReusableBuilder.scala index d7d3b6db4f09..246e525e37d9 100644 --- a/scala2-library-cc/src/scala/collection/mutable/ReusableBuilder.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ReusableBuilder.scala @@ -14,6 +14,7 @@ package scala package collection package mutable +import language.experimental.captureChecking /** `ReusableBuilder` is a marker trait that indicates that a `Builder` * can be reused to build more than one instance of a collection. In diff --git a/scala2-library-cc/src/scala/collection/mutable/Seq.scala b/scala2-library-cc/src/scala/collection/mutable/Seq.scala index e83d79987208..443eec379c1b 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Seq.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Seq.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.collection.{IterableFactoryDefaults, SeqFactory} +import language.experimental.captureChecking trait Seq[A] extends Iterable[A] diff --git a/scala2-library-cc/src/scala/collection/mutable/SeqMap.scala b/scala2-library-cc/src/scala/collection/mutable/SeqMap.scala index 67066f99e07e..5740490223b2 100644 --- a/scala2-library-cc/src/scala/collection/mutable/SeqMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/SeqMap.scala @@ -13,6 +13,7 @@ package scala package collection package mutable +import language.experimental.captureChecking /** * A generic trait for ordered mutable maps. Concrete classes have to provide diff --git a/scala2-library-cc/src/scala/collection/mutable/Set.scala b/scala2-library-cc/src/scala/collection/mutable/Set.scala index 6530e8fedf05..01384e993e89 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Set.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Set.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.collection.{IterableFactory, IterableFactoryDefaults, IterableOps} +import language.experimental.captureChecking /** Base trait for mutable sets */ trait Set[A] diff --git a/scala2-library-cc/src/scala/collection/mutable/Shrinkable.scala b/scala2-library-cc/src/scala/collection/mutable/Shrinkable.scala index 006a3b88e49f..de2a24ecf01f 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Shrinkable.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Shrinkable.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.annotation.tailrec +import language.experimental.captureChecking /** This trait forms part of collections that can be reduced * using a `-=` operator. @@ -52,7 +53,7 @@ trait Shrinkable[-A] { * @param xs the iterator producing the elements to remove. * @return the $coll itself */ - def subtractAll(xs: collection.IterableOnce[A]): this.type = { + def subtractAll(xs: collection.IterableOnce[A]^): this.type = { @tailrec def loop(xs: collection.LinearSeq[A]): Unit = { if (xs.nonEmpty) { subtractOne(xs.head) @@ -74,6 +75,6 @@ trait Shrinkable[-A] { } /** Alias for `subtractAll` */ - @`inline` final def --= (xs: collection.IterableOnce[A]): this.type = subtractAll(xs) + @`inline` final def --= (xs: collection.IterableOnce[A]^): this.type = subtractAll(xs) } diff --git a/scala2-library-cc/src/scala/collection/mutable/SortedMap.scala b/scala2-library-cc/src/scala/collection/mutable/SortedMap.scala index eb2f0d231b7a..8017177f5720 100644 --- a/scala2-library-cc/src/scala/collection/mutable/SortedMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/SortedMap.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.collection.{SortedMapFactory, SortedMapFactoryDefaults} +import language.experimental.captureChecking /** * Base type for mutable sorted map collections @@ -37,7 +38,7 @@ trait SortedMap[K, V] * @param d the function mapping keys to values, used for non-present keys * @return a wrapper of the map with a default value */ - override def withDefault(d: K => V): SortedMap[K, V] = new SortedMap.WithDefault[K, V](this, d) + override def withDefault(d: K -> V): SortedMap[K, V] = new SortedMap.WithDefault[K, V](this, d) /** The same map with a given default value. * Note: The default is only used for `apply`. Other methods like `get`, `contains`, `iterator`, `keys`, etc. @@ -66,7 +67,7 @@ trait SortedMapOps[K, V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { @SerialVersionUID(3L) - final class WithDefault[K, V](underlying: SortedMap[K, V], defaultValue: K => V) + final class WithDefault[K, V](underlying: SortedMap[K, V], defaultValue: K -> V) extends Map.WithDefault[K, V](underlying, defaultValue) with SortedMap[K, V] with SortedMapOps[K, V, SortedMap, WithDefault[K, V]] @@ -91,10 +92,10 @@ object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) - override def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]): SortedMap[K, V2] = + override def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]^): SortedMap[K, V2] = underlying.concat(suffix).withDefault(defaultValue) - override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)]): WithDefault[K, V] = + override protected def fromSpecific(coll: scala.collection.IterableOnce[(K, V)]^): WithDefault[K, V] = new WithDefault[K, V](sortedMapFactory.from(coll), defaultValue) override protected def newSpecificBuilder: Builder[(K, V), WithDefault[K, V]] = diff --git a/scala2-library-cc/src/scala/collection/mutable/SortedSet.scala b/scala2-library-cc/src/scala/collection/mutable/SortedSet.scala index 2bcb8dc7845a..e657fb749d7d 100644 --- a/scala2-library-cc/src/scala/collection/mutable/SortedSet.scala +++ b/scala2-library-cc/src/scala/collection/mutable/SortedSet.scala @@ -13,6 +13,7 @@ package scala package collection package mutable +import language.experimental.captureChecking /** * Base type for mutable sorted set collections diff --git a/scala2-library-cc/src/scala/collection/mutable/Stack.scala b/scala2-library-cc/src/scala/collection/mutable/Stack.scala index 675666bc805c..0292811d2020 100644 --- a/scala2-library-cc/src/scala/collection/mutable/Stack.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Stack.scala @@ -16,6 +16,8 @@ import scala.annotation.{migration, nowarn} import scala.collection.generic.DefaultSerializable import scala.collection.{IterableFactoryDefaults, IterableOnce, SeqFactory, StrictOptimizedSeqFactory, StrictOptimizedSeqOps} +import language.experimental.captureChecking + /** A stack implements a data structure which allows to store and retrieve * objects in a last-in-first-out (LIFO) fashion. * @@ -133,7 +135,7 @@ class Stack[A] protected (array: Array[AnyRef], start: Int, end: Int) @SerialVersionUID(3L) object Stack extends StrictOptimizedSeqFactory[Stack] { - def from[A](source: IterableOnce[A]): Stack[A] = empty ++= source + def from[A](source: IterableOnce[A]^): Stack[A] = empty ++= source def empty[A]: Stack[A] = new Stack diff --git a/scala2-library-cc/src/scala/collection/mutable/StringBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/StringBuilder.scala index 1d8b9563e917..c7859214821d 100644 --- a/scala2-library-cc/src/scala/collection/mutable/StringBuilder.scala +++ b/scala2-library-cc/src/scala/collection/mutable/StringBuilder.scala @@ -14,6 +14,7 @@ package scala.collection.mutable import scala.collection.{IterableFactoryDefaults, IterableOnce} import scala.collection.immutable.WrappedString +import language.experimental.captureChecking import scala.Predef.{ // unimport char-related implicit conversions to avoid triggering them accidentally genericArrayOps => _, @@ -81,7 +82,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr // Methods required to make this an IndexedSeq: def apply(i: Int): Char = underlying.charAt(i) - override protected def fromSpecific(coll: scala.collection.IterableOnce[Char]): StringBuilder = + override protected def fromSpecific(coll: scala.collection.IterableOnce[Char]^): StringBuilder = new StringBuilder() appendAll coll override protected def newSpecificBuilder: Builder[Char, StringBuilder] = @@ -184,7 +185,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr * @param xs the characters to be appended. * @return this StringBuilder. */ - def appendAll(xs: IterableOnce[Char]): this.type = { + def appendAll(xs: IterableOnce[Char]^): this.type = { xs match { case x: WrappedString => underlying append x.unwrap case x: ArraySeq.ofChar => underlying append x.array @@ -313,7 +314,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr * @return this StringBuilder. * @throws StringIndexOutOfBoundsException if the index is out of bounds. */ - def insertAll(index: Int, xs: IterableOnce[Char]): this.type = + def insertAll(index: Int, xs: IterableOnce[Char]^): this.type = insertAll(index, (ArrayBuilder.make[Char] ++= xs).result()) /** Inserts the given Array[Char] into this sequence at the given index. diff --git a/scala2-library-cc/src/scala/collection/mutable/TreeMap.scala b/scala2-library-cc/src/scala/collection/mutable/TreeMap.scala index 8fcb7b688a1f..d36e1b9d207d 100644 --- a/scala2-library-cc/src/scala/collection/mutable/TreeMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/TreeMap.scala @@ -17,6 +17,7 @@ package mutable import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.collection.mutable.{RedBlackTree => RB} +import language.experimental.captureChecking /** * A mutable sorted map implemented using a mutable red-black tree as underlying data structure. @@ -38,7 +39,7 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: with SortedMapFactoryDefaults[K, V, TreeMap, Iterable, Map] with DefaultSerializable { - override def sortedMapFactory: TreeMap.type = TreeMap + override def sortedMapFactory = TreeMap /** * Creates an empty `TreeMap`. @@ -247,7 +248,7 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: @SerialVersionUID(3L) object TreeMap extends SortedMapFactory[TreeMap] { - def from[K : Ordering, V](it: IterableOnce[(K, V)]): TreeMap[K, V] = + def from[K : Ordering, V](it: IterableOnce[(K, V)]^): TreeMap[K, V] = Growable.from(empty[K, V], it) def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap[K, V]() diff --git a/scala2-library-cc/src/scala/collection/mutable/TreeSet.scala b/scala2-library-cc/src/scala/collection/mutable/TreeSet.scala index bed474dc02a3..59c68a768351 100644 --- a/scala2-library-cc/src/scala/collection/mutable/TreeSet.scala +++ b/scala2-library-cc/src/scala/collection/mutable/TreeSet.scala @@ -17,6 +17,7 @@ import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.collection.mutable.{RedBlackTree => RB} import scala.collection.{SortedIterableFactory, SortedSetFactoryDefaults, Stepper, StepperShape, StrictOptimizedIterableOps, StrictOptimizedSortedSetOps, mutable} +import language.experimental.captureChecking /** * A mutable sorted set implemented using a mutable red-black tree as underlying data structure. @@ -193,7 +194,7 @@ object TreeSet extends SortedIterableFactory[TreeSet] { def empty[A : Ordering]: TreeSet[A] = new TreeSet[A]() - def from[E](it: IterableOnce[E])(implicit ordering: Ordering[E]): TreeSet[E] = + def from[E](it: IterableOnce[E]^)(implicit ordering: Ordering[E]): TreeSet[E] = it match { case ts: TreeSet[E] if ordering == ts.ordering => new TreeSet[E](ts.tree.treeCopy()) diff --git a/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala index b8a54a1f3fa5..cfb6d014ae9d 100644 --- a/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala +++ b/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala @@ -17,6 +17,7 @@ import scala.annotation.tailrec import scala.collection.generic.DefaultSerializable import scala.reflect.ClassTag import scala.collection.immutable.Nil +import language.experimental.captureChecking /** A buffer that stores elements in an unrolled linked list. * @@ -72,7 +73,7 @@ sealed class UnrolledBuffer[T](implicit val tag: ClassTag[T]) override def iterableFactory: SeqFactory[UnrolledBuffer] = UnrolledBuffer.untagged - protected def newUnrolled = new Unrolled[T](this) + protected def newUnrolled: Unrolled[T] = new Unrolled[T](this) // The below would allow more flexible behavior without requiring inheritance // that is risky because all the important internals are private. @@ -89,7 +90,7 @@ sealed class UnrolledBuffer[T](implicit val tag: ClassTag[T]) // def setLengthPolicy(nextLength: Int => Int): Unit = { myLengthPolicy = nextLength } private[collection] def calcNextLength(sz: Int) = sz // myLengthPolicy(sz) - def classTagCompanion: UnrolledBuffer.type = UnrolledBuffer + def classTagCompanion = UnrolledBuffer /** Concatenates the target unrolled buffer to this unrolled buffer. * @@ -190,7 +191,7 @@ sealed class UnrolledBuffer[T](implicit val tag: ClassTag[T]) def insert(idx: Int, elem: T): Unit = insertAll(idx, elem :: Nil) - def insertAll(idx: Int, elems: IterableOnce[T]): Unit = + def insertAll(idx: Int, elems: IterableOnce[T]^): Unit = if (idx >= 0 && idx <= sz) { sz += headptr.insertAll(idx, elems, this) } else throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${sz-1})") @@ -202,7 +203,7 @@ sealed class UnrolledBuffer[T](implicit val tag: ClassTag[T]) this } - def patchInPlace(from: Int, patch: collection.IterableOnce[T], replaced: Int): this.type = { + def patchInPlace(from: Int, patch: collection.IterableOnce[T]^, replaced: Int): this.type = { remove(from, replaced) insertAll(from, patch) this @@ -242,7 +243,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] def empty[A : ClassTag]: UnrolledBuffer[A] = new UnrolledBuffer[A] - def from[A : ClassTag](source: scala.collection.IterableOnce[A]): UnrolledBuffer[A] = newBuilder[A].addAll(source) + def from[A : ClassTag](source: scala.collection.IterableOnce[A]^): UnrolledBuffer[A] = newBuilder[A].addAll(source) def newBuilder[A : ClassTag]: UnrolledBuffer[A] = new UnrolledBuffer[A] @@ -372,7 +373,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] if (next eq null) true else false // checks if last node was thrown out } else false - @tailrec final def insertAll(idx: Int, t: scala.collection.IterableOnce[T], buffer: UnrolledBuffer[T]): Int = { + @tailrec final def insertAll(idx: Int, t: scala.collection.IterableOnce[T]^, buffer: UnrolledBuffer[T]): Int = { if (idx < size) { // divide this node at the appropriate position and insert all into head // update new next diff --git a/scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala index 7286a318e1f9..1ccd36c3e25f 100644 --- a/scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala @@ -16,6 +16,7 @@ package mutable import scala.annotation.nowarn import scala.collection.convert.JavaCollectionWrappers.{JMapWrapper, JMapWrapperLike} +import language.experimental.captureChecking /** A hash map with references to entries which are weakly reachable. Entries are * removed from this map when the key is no longer (strongly) referenced. This class wraps @@ -49,7 +50,7 @@ class WeakHashMap[K, V] extends JMapWrapper[K, V](new java.util.WeakHashMap) @SerialVersionUID(3L) object WeakHashMap extends MapFactory[WeakHashMap] { def empty[K, V]: WeakHashMap[K,V] = new WeakHashMap[K, V] - def from[K, V](it: collection.IterableOnce[(K, V)]): WeakHashMap[K,V] = Growable.from(empty[K, V], it) + def from[K, V](it: collection.IterableOnce[(K, V)]^): WeakHashMap[K,V] = Growable.from(empty[K, V], it) def newBuilder[K, V]: Builder[(K, V), WeakHashMap[K,V]] = new GrowableBuilder(WeakHashMap.empty[K, V]) } diff --git a/scala2-library-cc/src/scala/collection/mutable/package.scala b/scala2-library-cc/src/scala/collection/mutable/package.scala index 4915e8a48b22..d658ca5bc65a 100644 --- a/scala2-library-cc/src/scala/collection/mutable/package.scala +++ b/scala2-library-cc/src/scala/collection/mutable/package.scala @@ -11,6 +11,7 @@ */ package scala.collection +import language.experimental.captureChecking package object mutable { diff --git a/scala2-library-cc/src/scala/collection/package.scala b/scala2-library-cc/src/scala/collection/package.scala index 954573ff1ddd..ad4686be1fb2 100644 --- a/scala2-library-cc/src/scala/collection/package.scala +++ b/scala2-library-cc/src/scala/collection/package.scala @@ -11,6 +11,7 @@ */ package scala +import language.experimental.captureChecking package object collection { @deprecated("Use Iterable instead of Traversable", "2.13.0") diff --git a/scala2-library-cc/src/scala/runtime/PStatics.scala b/scala2-library-cc/src/scala/runtime/PStatics.scala new file mode 100644 index 000000000000..788a56962855 --- /dev/null +++ b/scala2-library-cc/src/scala/runtime/PStatics.scala @@ -0,0 +1,19 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.runtime + +// things that should be in `Statics`, but can't be yet for bincompat reasons +// TODO 3.T: move to `Statics` +private[scala] object PStatics { + final val VM_MaxArraySize = 2147483645 // == `Int.MaxValue - 2`, hotspot limit +}