diff --git a/library-js/src/scala/Array.scala b/library-js/src/scala/Array.scala index f0cd45af9dde..a71624a2081e 100644 --- a/library-js/src/scala/Array.scala +++ b/library-js/src/scala/Array.scala @@ -12,6 +12,8 @@ package scala +import language.experimental.captureChecking + //import scala.collection.generic._ import scala.collection.{Factory, immutable, mutable} import mutable.ArrayBuilder @@ -61,7 +63,7 @@ object Array { implicit def toFactory[A : ClassTag](dummy: Array.type): Factory[A, Array[A]] = new ArrayFactory(dummy) @SerialVersionUID(3L) private class ArrayFactory[A : ClassTag](dummy: Array.type) extends Factory[A, Array[A]] with Serializable { - def fromSpecific(it: IterableOnce[A]): Array[A] = Array.from[A](it) + def fromSpecific(it: IterableOnce[A]^): Array[A] = Array.from[A](it) def newBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder[A] } @@ -70,7 +72,7 @@ object Array { */ def newBuilder[T](implicit t: ClassTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T](using t) - def from[A : ClassTag](it: IterableOnce[A]): Array[A] = { + def from[A: ClassTag](it: IterableOnce[A]^): Array[A] = { val n = it.knownSize if (n > -1) { val elements = new Array[A](n) @@ -656,7 +658,7 @@ object Array { * @define collectExample * @define undefinedorder */ -final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { +final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { self => /** The length of the array */ def length: Int = throw new Error() diff --git a/library/src/scala/Array.scala b/library/src/scala/Array.scala index 8daa1859cf44..bb23b79eb1a4 100644 --- a/library/src/scala/Array.scala +++ b/library/src/scala/Array.scala @@ -13,6 +13,7 @@ package scala import scala.language.`2.13` +import language.experimental.captureChecking //import scala.collection.generic._ import scala.collection.{Factory, immutable, mutable} @@ -49,7 +50,7 @@ object Array { implicit def toFactory[A : ClassTag](dummy: Array.type): Factory[A, Array[A]] = new ArrayFactory(dummy) @SerialVersionUID(3L) private class ArrayFactory[A : ClassTag](dummy: Array.type) extends Factory[A, Array[A]] with Serializable { - def fromSpecific(it: IterableOnce[A]): Array[A] = Array.from[A](it) + def fromSpecific(it: IterableOnce[A]^): Array[A] = Array.from[A](it) def newBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder[A] } @@ -71,7 +72,7 @@ object Array { * @param it the iterable collection * @return an array consisting of elements of the iterable collection */ - def from[A : ClassTag](it: IterableOnce[A]): Array[A] = it match { + def from[A : ClassTag](it: IterableOnce[A]^): Array[A] = it match { case it: Iterable[A] => it.toArray[A] case _ => it.iterator.toArray[A] } @@ -659,7 +660,7 @@ object Array { * @define collectExample * @define undefinedorder */ -final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { +final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { self: Array[T] => /** The length of the array */ def length: Int = throw new Error() diff --git a/library/src/scala/Boolean.scala b/library/src/scala/Boolean.scala index 5ff37694d133..5df9184b5e30 100644 --- a/library/src/scala/Boolean.scala +++ b/library/src/scala/Boolean.scala @@ -114,7 +114,7 @@ final abstract class Boolean private extends AnyVal { object Boolean extends AnyValCompanion { - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToBoolean`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -123,7 +123,7 @@ object Boolean extends AnyValCompanion { */ def box(x: Boolean): java.lang.Boolean = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Boolean. * diff --git a/library/src/scala/Byte.scala b/library/src/scala/Byte.scala index c5891be37e36..c1f0e81f746b 100644 --- a/library/src/scala/Byte.scala +++ b/library/src/scala/Byte.scala @@ -455,7 +455,7 @@ object Byte extends AnyValCompanion { /** The largest value representable as a Byte. */ final val MaxValue = java.lang.Byte.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToByte`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -464,7 +464,7 @@ object Byte extends AnyValCompanion { */ def box(x: Byte): java.lang.Byte = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Byte. * diff --git a/library/src/scala/Char.scala b/library/src/scala/Char.scala index 500ffcb05412..06a6e186901b 100644 --- a/library/src/scala/Char.scala +++ b/library/src/scala/Char.scala @@ -455,7 +455,7 @@ object Char extends AnyValCompanion { /** The largest value representable as a Char. */ final val MaxValue = java.lang.Character.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToCharacter`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -464,7 +464,7 @@ object Char extends AnyValCompanion { */ def box(x: Char): java.lang.Character = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Character. * diff --git a/library/src/scala/Double.scala b/library/src/scala/Double.scala index 08a91bf8c603..57e99999198b 100644 --- a/library/src/scala/Double.scala +++ b/library/src/scala/Double.scala @@ -230,7 +230,7 @@ object Double extends AnyValCompanion { /** The largest finite positive number representable as a Double. */ final val MaxValue = java.lang.Double.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToDouble`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -239,7 +239,7 @@ object Double extends AnyValCompanion { */ def box(x: Double): java.lang.Double = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Double. * diff --git a/library/src/scala/Float.scala b/library/src/scala/Float.scala index fae92d99e882..1f8b00886258 100644 --- a/library/src/scala/Float.scala +++ b/library/src/scala/Float.scala @@ -230,7 +230,7 @@ object Float extends AnyValCompanion { /** The largest finite positive number representable as a Float. */ final val MaxValue = java.lang.Float.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToFloat`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -239,7 +239,7 @@ object Float extends AnyValCompanion { */ def box(x: Float): java.lang.Float = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Float. * diff --git a/library/src/scala/Function0.scala b/library/src/scala/Function0.scala index af9327e6e88c..0dd571885a43 100644 --- a/library/src/scala/Function0.scala +++ b/library/src/scala/Function0.scala @@ -11,7 +11,7 @@ */ // GENERATED CODE: DO NOT EDIT. -// genprod generated these sources at: 2022-01-17T20:47:12.170348200Z +// genprod generated these sources at: 2025-08-11T16:44:44.712777821Z package scala @@ -36,7 +36,7 @@ import scala.language.`2.13` * } * }}} */ -trait Function0[@specialized(Specializable.Primitives) +R] extends AnyRef { self => +trait Function0[@specialized(Specializable.Primitives) +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ diff --git a/library/src/scala/Function1.scala b/library/src/scala/Function1.scala index b31ed60766d5..ece9d778aa7b 100644 --- a/library/src/scala/Function1.scala +++ b/library/src/scala/Function1.scala @@ -65,7 +65,7 @@ object Function1 { * is that the latter can specify inputs which it will not handle. */ @annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.") -trait Function1[@specialized(Specializable.Arg) -T1, @specialized(Specializable.Return) +R] extends AnyRef { self => +trait Function1[@specialized(Specializable.Arg) -T1, @specialized(Specializable.Return) +R] extends AnyRef { /** Apply the body of this function to the argument. * @return the result of function application. */ diff --git a/library/src/scala/Function10.scala b/library/src/scala/Function10.scala index c362ea877732..823544865d54 100644 --- a/library/src/scala/Function10.scala +++ b/library/src/scala/Function10.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 10 parameters. * */ -trait Function10[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, +R] extends AnyRef { self => +trait Function10[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function10[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, +R] extends * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)).curried } /** Creates a tupled version of this function: instead of 10 arguments, * it accepts a single [[scala.Tuple10]] argument. diff --git a/library/src/scala/Function11.scala b/library/src/scala/Function11.scala index 1706470355c3..bd4b3fb394ad 100644 --- a/library/src/scala/Function11.scala +++ b/library/src/scala/Function11.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 11 parameters. * */ -trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R] extends AnyRef { self => +trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R] ex * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)).curried } /** Creates a tupled version of this function: instead of 11 arguments, * it accepts a single [[scala.Tuple11]] argument. diff --git a/library/src/scala/Function12.scala b/library/src/scala/Function12.scala index 5ccaa7722095..42c5ba6aa645 100644 --- a/library/src/scala/Function12.scala +++ b/library/src/scala/Function12.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 12 parameters. * */ -trait Function12[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, +R] extends AnyRef { self => +trait Function12[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function12[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)).curried } /** Creates a tupled version of this function: instead of 12 arguments, * it accepts a single [[scala.Tuple12]] argument. diff --git a/library/src/scala/Function13.scala b/library/src/scala/Function13.scala index a92b6710bbfb..074c69b779c1 100644 --- a/library/src/scala/Function13.scala +++ b/library/src/scala/Function13.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 13 parameters. * */ -trait Function13[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, +R] extends AnyRef { self => +trait Function13[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function13[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)).curried } /** Creates a tupled version of this function: instead of 13 arguments, * it accepts a single [[scala.Tuple13]] argument. diff --git a/library/src/scala/Function14.scala b/library/src/scala/Function14.scala index 687a3e693766..06332ea72f66 100644 --- a/library/src/scala/Function14.scala +++ b/library/src/scala/Function14.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 14 parameters. * */ -trait Function14[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, +R] extends AnyRef { self => +trait Function14[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function14[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)).curried } /** Creates a tupled version of this function: instead of 14 arguments, * it accepts a single [[scala.Tuple14]] argument. diff --git a/library/src/scala/Function15.scala b/library/src/scala/Function15.scala index c45cae4e1a97..5b4c022bef76 100644 --- a/library/src/scala/Function15.scala +++ b/library/src/scala/Function15.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 15 parameters. * */ -trait Function15[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, +R] extends AnyRef { self => +trait Function15[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function15[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)).curried } /** Creates a tupled version of this function: instead of 15 arguments, * it accepts a single [[scala.Tuple15]] argument. diff --git a/library/src/scala/Function16.scala b/library/src/scala/Function16.scala index 8795ccfbd546..937ee43ef768 100644 --- a/library/src/scala/Function16.scala +++ b/library/src/scala/Function16.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 16 parameters. * */ -trait Function16[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, +R] extends AnyRef { self => +trait Function16[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function16[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)).curried } /** Creates a tupled version of this function: instead of 16 arguments, * it accepts a single [[scala.Tuple16]] argument. diff --git a/library/src/scala/Function17.scala b/library/src/scala/Function17.scala index 874ea3bcd9fc..4e054ba2833d 100644 --- a/library/src/scala/Function17.scala +++ b/library/src/scala/Function17.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 17 parameters. * */ -trait Function17[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, +R] extends AnyRef { self => +trait Function17[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function17[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)).curried } /** Creates a tupled version of this function: instead of 17 arguments, * it accepts a single [[scala.Tuple17]] argument. diff --git a/library/src/scala/Function18.scala b/library/src/scala/Function18.scala index 4fa20a649416..cceb289ab6f9 100644 --- a/library/src/scala/Function18.scala +++ b/library/src/scala/Function18.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 18 parameters. * */ -trait Function18[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, +R] extends AnyRef { self => +trait Function18[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function18[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)).curried } /** Creates a tupled version of this function: instead of 18 arguments, * it accepts a single [[scala.Tuple18]] argument. diff --git a/library/src/scala/Function19.scala b/library/src/scala/Function19.scala index c59e32b4ae40..88a3dd10d9be 100644 --- a/library/src/scala/Function19.scala +++ b/library/src/scala/Function19.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 19 parameters. * */ -trait Function19[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, +R] extends AnyRef { self => +trait Function19[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function19[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)).curried } /** Creates a tupled version of this function: instead of 19 arguments, * it accepts a single [[scala.Tuple19]] argument. diff --git a/library/src/scala/Function2.scala b/library/src/scala/Function2.scala index ccb066fb9f3a..ecb760e4e39c 100644 --- a/library/src/scala/Function2.scala +++ b/library/src/scala/Function2.scala @@ -34,7 +34,7 @@ import scala.language.`2.13` * } * }}} */ -trait Function2[@specialized(Specializable.Args) -T1, @specialized(Specializable.Args) -T2, @specialized(Specializable.Return) +R] extends AnyRef { self => +trait Function2[@specialized(Specializable.Args) -T1, @specialized(Specializable.Args) -T2, @specialized(Specializable.Return) +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ diff --git a/library/src/scala/Function20.scala b/library/src/scala/Function20.scala index 1b445f783310..aac19a4309fc 100644 --- a/library/src/scala/Function20.scala +++ b/library/src/scala/Function20.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 20 parameters. * */ -trait Function20[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, +R] extends AnyRef { self => +trait Function20[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function20[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)).curried } /** Creates a tupled version of this function: instead of 20 arguments, * it accepts a single [[scala.Tuple20]] argument. diff --git a/library/src/scala/Function21.scala b/library/src/scala/Function21.scala index e5e3047da3b3..cf5231f08939 100644 --- a/library/src/scala/Function21.scala +++ b/library/src/scala/Function21.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 21 parameters. * */ -trait Function21[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, -T21, +R] extends AnyRef { self => +trait Function21[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, -T21, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function21[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)).curried } /** Creates a tupled version of this function: instead of 21 arguments, * it accepts a single [[scala.Tuple21]] argument. diff --git a/library/src/scala/Function22.scala b/library/src/scala/Function22.scala index 9eae1d43ce26..21e52c9d5562 100644 --- a/library/src/scala/Function22.scala +++ b/library/src/scala/Function22.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 22 parameters. * */ -trait Function22[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, -T21, -T22, +R] extends AnyRef { self => +trait Function22[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, -T21, -T22, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function22[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21)(x22) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => T22 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21, x22: T22) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21, x22: T22) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)).curried } /** Creates a tupled version of this function: instead of 22 arguments, * it accepts a single [[scala.Tuple22]] argument. diff --git a/library/src/scala/Function3.scala b/library/src/scala/Function3.scala index 5c29f6e4fbbd..b7cbec633261 100644 --- a/library/src/scala/Function3.scala +++ b/library/src/scala/Function3.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 3 parameters. * */ -trait Function3[-T1, -T2, -T3, +R] extends AnyRef { self => +trait Function3[-T1, -T2, -T3, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ diff --git a/library/src/scala/Function4.scala b/library/src/scala/Function4.scala index efc3c56909eb..062a92b4abfc 100644 --- a/library/src/scala/Function4.scala +++ b/library/src/scala/Function4.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 4 parameters. * */ -trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef { self => +trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ diff --git a/library/src/scala/Function5.scala b/library/src/scala/Function5.scala index a0e4b082c728..75115c78379d 100644 --- a/library/src/scala/Function5.scala +++ b/library/src/scala/Function5.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 5 parameters. * */ -trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef { self => +trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef { self => * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5) == apply(x1, x2, x3, x4, x5)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5) => self.apply(x1, x2, x3, x4, x5)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5) => this.apply(x1, x2, x3, x4, x5)).curried } /** Creates a tupled version of this function: instead of 5 arguments, * it accepts a single [[scala.Tuple5]] argument. diff --git a/library/src/scala/Function6.scala b/library/src/scala/Function6.scala index 58d428c8e888..99f4b4a2ffda 100644 --- a/library/src/scala/Function6.scala +++ b/library/src/scala/Function6.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 6 parameters. * */ -trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef { self => +trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef { self => * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6) == apply(x1, x2, x3, x4, x5, x6)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6) => self.apply(x1, x2, x3, x4, x5, x6)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6) => this.apply(x1, x2, x3, x4, x5, x6)).curried } /** Creates a tupled version of this function: instead of 6 arguments, * it accepts a single [[scala.Tuple6]] argument. diff --git a/library/src/scala/Function7.scala b/library/src/scala/Function7.scala index 8f4bfa19aa9d..04f54559b230 100644 --- a/library/src/scala/Function7.scala +++ b/library/src/scala/Function7.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 7 parameters. * */ -trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef { self => +trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef { self => * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7) == apply(x1, x2, x3, x4, x5, x6, x7)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7) => self.apply(x1, x2, x3, x4, x5, x6, x7)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7) => this.apply(x1, x2, x3, x4, x5, x6, x7)).curried } /** Creates a tupled version of this function: instead of 7 arguments, * it accepts a single [[scala.Tuple7]] argument. diff --git a/library/src/scala/Function8.scala b/library/src/scala/Function8.scala index 384f6132d1a5..44394a42915d 100644 --- a/library/src/scala/Function8.scala +++ b/library/src/scala/Function8.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 8 parameters. * */ -trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef { self => +trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef { sel * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8) == apply(x1, x2, x3, x4, x5, x6, x7, x8)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8)).curried } /** Creates a tupled version of this function: instead of 8 arguments, * it accepts a single [[scala.Tuple8]] argument. diff --git a/library/src/scala/Function9.scala b/library/src/scala/Function9.scala index a60f59f0f25d..76b42793a06d 100644 --- a/library/src/scala/Function9.scala +++ b/library/src/scala/Function9.scala @@ -19,7 +19,7 @@ import scala.language.`2.13` /** A function of 9 parameters. * */ -trait Function9[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, +R] extends AnyRef { self => +trait Function9[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, +R] extends AnyRef { /** Apply the body of this function to the arguments. * @return the result of function application. */ @@ -29,7 +29,7 @@ trait Function9[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, +R] extends AnyRef * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)` */ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => R = { - (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)).curried + (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9) => this.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)).curried } /** Creates a tupled version of this function: instead of 9 arguments, * it accepts a single [[scala.Tuple9]] argument. diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 12eac3985626..281d1ef78a89 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -272,9 +272,9 @@ object IArray: def concat[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).concat(suffix) def concat[U >: T: ClassTag](suffix: IterableOnce[U]^): IArray[U] = genericArrayOps(arr).concat(suffix) def diff[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).diff(that.toSeq) - def diff[U >: T](that: Seq[U]^): IArray[T] = genericArrayOps(arr).diff(that) + def diff[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).diff(that) def distinct: IArray[T] = genericArrayOps(arr).distinct - def distinctBy[U](f: T => U): IArray[T] = genericArrayOps(arr).distinctBy(f) + def distinctBy[U](f: T -> U): IArray[T] = genericArrayOps(arr).distinctBy(f) def startsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) def startsWith[U >: T](that: IArray[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) def startsWith[U >: T](that: IterableOnce[U]^): Boolean = genericArrayOps(arr).startsWith(that, 0) @@ -286,7 +286,7 @@ object IArray: def grouped(size: Int): Iterator[IArray[T]] = genericArrayOps(arr).grouped(size) def inits: Iterator[IArray[T]] = genericArrayOps(arr).inits def intersect[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).intersect(that) - def intersect[U >: T](that: Seq[U]^): IArray[T] = genericArrayOps(arr).intersect(that) + def intersect[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).intersect(that) def lazyZip[U](that: IArray[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] def lazyZip[U](that: Iterable[U]^): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] def lengthCompare(len: Int): Int = genericArrayOps(arr).lengthCompare(len) @@ -297,7 +297,7 @@ object IArray: def prepended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).prepended(x) def prependedAll[U >: T: ClassTag](prefix: IterableOnce[U]^): IArray[U] = genericArrayOps(arr).prependedAll(prefix) def reverseIterator: Iterator[T] = genericArrayOps(arr).reverseIterator - def search[U >: T](elem: U)(using Ordering[U]^): Searching.SearchResult = arr.toSeq.search(elem) + def search[U >: T](elem: U)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem) def search[U >: T](elem: U, from: Int, to: Int)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem, from, to) def sizeCompare(that: IArray[Any]): Int = arr.toSeq.sizeCompare(that) def sizeCompare(that: Iterable[?]): Int = arr.toSeq.sizeCompare(that) diff --git a/library/src/scala/Int.scala b/library/src/scala/Int.scala index 335e33233541..a3fff7e991da 100644 --- a/library/src/scala/Int.scala +++ b/library/src/scala/Int.scala @@ -455,7 +455,7 @@ object Int extends AnyValCompanion { /** The largest value representable as an Int. */ final val MaxValue = java.lang.Integer.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToInteger`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -464,7 +464,7 @@ object Int extends AnyValCompanion { */ def box(x: Int): java.lang.Integer = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Integer. * diff --git a/library/src/scala/Long.scala b/library/src/scala/Long.scala index e19b7e706f96..2561c1ec74c2 100644 --- a/library/src/scala/Long.scala +++ b/library/src/scala/Long.scala @@ -452,7 +452,7 @@ object Long extends AnyValCompanion { /** The largest value representable as a Long. */ final val MaxValue = java.lang.Long.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToLong`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -461,7 +461,7 @@ object Long extends AnyValCompanion { */ def box(x: Long): java.lang.Long = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Long. * diff --git a/library/src/scala/PartialFunction.scala b/library/src/scala/PartialFunction.scala index af8199d6209e..31f3fbe77a83 100644 --- a/library/src/scala/PartialFunction.scala +++ b/library/src/scala/PartialFunction.scala @@ -15,6 +15,8 @@ package scala import scala.language.`2.13` import scala.annotation.nowarn +import language.experimental.captureChecking + /** A partial function of type `PartialFunction[A, B]` is a unary function * where the domain does not necessarily include all values of type `A`. * The function [[isDefinedAt]] allows to test dynamically if a value is in @@ -105,7 +107,7 @@ import scala.annotation.nowarn * may apply the first partial function and execute its side effect. * For efficiency, it is recommended to call [[applyOrElse]] instead of [[isDefinedAt]] or [[apply]]. */ -trait PartialFunction[-A, +B] extends (A => B) { self => +trait PartialFunction[-A, +B] extends Function1[A, B] { self: PartialFunction[A, B]^ => import PartialFunction._ /** Tries to extract a `B` from an `A` in a pattern matching expression. */ @@ -122,7 +124,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * } * }}} */ - def elementWise: ElementWiseExtractor[A, B] = new ElementWiseExtractor[A, B](this) + def elementWise: ElementWiseExtractor[A, B]^{this} = new ElementWiseExtractor[A, B](this) /** Checks if a value is contained in the function's domain. * @@ -141,7 +143,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * of this partial function and `that`. The resulting partial function * takes `x` to `this(x)` where `this` is defined, and to `that(x)` where it is not. */ - def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = + def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]^): PartialFunction[A1, B1]^{this, that} = new OrElse[A1, B1] (this, that) //TODO: why not overload it with orElse(that: F1): F1? @@ -157,8 +159,8 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * possibly narrowed by the specified function, which maps * arguments `x` to `k(this(x))`. */ - override def andThen[C](k: B => C): PartialFunction[A, C] = k match { - case pf: PartialFunction[B, C] => andThen(pf) + override def andThen[C](k: B => C): PartialFunction[A, C]^{this, k} = k match { + case pf: (PartialFunction[B, C]^{k}) => andThen(pf) case _ => new AndThen[A, B, C](this, k) } @@ -173,7 +175,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * @return a partial function with the domain of this partial function narrowed by * other partial function, which maps arguments `x` to `k(this(x))`. */ - def andThen[C](k: PartialFunction[B, C]): PartialFunction[A, C] = + def andThen[C](k: PartialFunction[B, C]^): PartialFunction[A, C]^{this, k} = new Combined[A, B, C](this, k) /** @@ -187,7 +189,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * @return a partial function with the domain of other partial function narrowed by * this partial function, which maps arguments `x` to `this(k(x))`. */ - def compose[R](k: PartialFunction[R, A]): PartialFunction[R, B] = + def compose[R](k: PartialFunction[R, A]^): PartialFunction[R, B]^{this, k} = new Combined[R, A, B](k, this) /** Turns this partial function into a plain function returning an `Option` result. @@ -195,7 +197,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * @return a function that takes an argument `x` to `Some(this(x))` if `this` * is defined for `x`, and to `None` otherwise. */ - def lift: A => Option[B] = new Lifted(this) + def lift: A ->{this} Option[B] = new Lifted(this) /** Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined. @@ -239,7 +241,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * @return a function which maps arguments `x` to `isDefinedAt(x)`. The resulting function * runs `action(this(x))` where `this` is defined. */ - def runWith[U](action: B => U): A => Boolean = { x => + def runWith[U](action: B => U): A ->{this, action} Boolean = { x => val z = applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(z)) { action(z); true } else false } @@ -259,7 +261,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => */ object PartialFunction { - final class ElementWiseExtractor[-A, +B] private[PartialFunction] (private val pf: PartialFunction[A, B]) extends AnyVal { + final class ElementWiseExtractor[-A, +B] private[PartialFunction] (private val pf: PartialFunction[A, B]^) extends AnyVal { this: ElementWiseExtractor[A, B]^ => @nowarn("cat=lint-nonlocal-return") def unapplySeq(seq: Seq[A]): Option[Seq[B]] = { Some(seq.map { @@ -271,7 +273,7 @@ object PartialFunction { /** Composite function produced by `PartialFunction#orElse` method */ - private class OrElse[-A, +B] (f1: PartialFunction[A, B], f2: PartialFunction[A, B]) + private class OrElse[-A, +B] (f1: PartialFunction[A, B]^, f2: PartialFunction[A, B]^) extends scala.runtime.AbstractPartialFunction[A, B] with Serializable { def isDefinedAt(x: A) = f1.isDefinedAt(x) || f2.isDefinedAt(x) @@ -282,16 +284,16 @@ object PartialFunction { if (!fallbackOccurred(z)) z else f2.applyOrElse(x, default) } - override def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): OrElse[A1, B1] = + override def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]^): OrElse[A1, B1]^{this, that} = new OrElse[A1, B1] (f1, f2 orElse that) - override def andThen[C](k: B => C): OrElse[A, C] = + override def andThen[C](k: B => C): OrElse[A, C]^{this, k} = new OrElse[A, C] (f1 andThen k, f2 andThen k) } /** Composite function produced by `PartialFunction#andThen` method */ - private class AndThen[-A, B, +C] (pf: PartialFunction[A, B], k: B => C) extends PartialFunction[A, C] with Serializable { + private class AndThen[-A, B, +C] (pf: PartialFunction[A, B]^, k: B => C) extends PartialFunction[A, C] with Serializable { def isDefinedAt(x: A) = pf.isDefinedAt(x) def apply(x: A): C = k(pf(x)) @@ -304,7 +306,7 @@ object PartialFunction { /** Composite function produced by `PartialFunction#andThen` method */ - private class Combined[-A, B, +C] (pf: PartialFunction[A, B], k: PartialFunction[B, C]) extends PartialFunction[A, C] with Serializable { + private class Combined[-A, B, +C] (pf: PartialFunction[A, B]^, k: PartialFunction[B, C]^) extends PartialFunction[A, C] with Serializable { def isDefinedAt(x: A): Boolean = { val b: B = pf.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(b)) k.isDefinedAt(b) else false @@ -339,11 +341,11 @@ object PartialFunction { * * Here `fallback_fn` is used as both unique marker object and special fallback function that returns it. */ - private[this] val fallback_fn: Any => Any = _ => fallback_fn + private[this] val fallback_fn: Any -> Any = _ => fallback_fn private def checkFallback[B] = fallback_fn.asInstanceOf[Any => B] private def fallbackOccurred[B](x: B) = fallback_fn eq x.asInstanceOf[AnyRef] - private class Lifted[-A, +B] (val pf: PartialFunction[A, B]) + private class Lifted[-A, +B] (val pf: PartialFunction[A, B]^) extends scala.runtime.AbstractFunction1[A, Option[B]] with Serializable { def apply(x: A): Option[B] = { @@ -362,9 +364,9 @@ object PartialFunction { override def lift = f } - private[scala] def unlifted[A, B](f: A => Option[B]): PartialFunction[A, B] = f match { - case lf: Lifted[A, B] => lf.pf - case ff => new Unlifted(ff) + private[scala] def unlifted[A, B](f: A => Option[B]): PartialFunction[A, B]^{f} = f match { + case lf: (Lifted[A, B]^{f}) => caps.unsafe.unsafeAssumePure(lf).pf // SAFETY: lf.pf captures at most pf + case _ => new Unlifted(f) } /** Converts an ordinary function to a partial function. Note that calling `isDefinedAt(x)` on @@ -372,16 +374,16 @@ object PartialFunction { * @param f an ordinary function * @return a partial function which delegates to the ordinary function `f` */ - def fromFunction[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) } + def fromFunction[A, B](f: A => B): PartialFunction[A, B]^{f} = { case x => f(x) } - private[this] val constFalse: Any => Boolean = { _ => false} + private[this] val constFalse: Any -> Boolean = { _ => false} private[this] val empty_pf: PartialFunction[Any, Nothing] = new PartialFunction[Any, Nothing] with Serializable { def isDefinedAt(x: Any) = false def apply(x: Any) = throw new MatchError(x) - override def orElse[A1, B1](that: PartialFunction[A1, B1]) = that - override def andThen[C](k: Nothing => C): PartialFunction[Any, Nothing] = this - override val lift: Any => None.type = (x: Any) => None + override def orElse[A1, B1](that: PartialFunction[A1, B1]^) = that + override def andThen[C](k: PartialFunction[Nothing, C]^): PartialFunction[Any, C]^{k} = this + override val lift: Any -> None.type = (x: Any) => None override def runWith[U](action: Nothing => U) = constFalse } @@ -399,7 +401,7 @@ object PartialFunction { * @param pf the partial function * @return true, iff `x` is in the domain of `pf` and `pf(x) == true`. */ - def cond[A](x: A)(pf: PartialFunction[A, Boolean]): Boolean = pf.applyOrElse(x, constFalse) + def cond[A](x: A)(pf: PartialFunction[A, Boolean]^): Boolean = pf.applyOrElse(x, constFalse) /** Apply the function to the given value if defined, and return the result * in a `Some`; otherwise, return `None`. @@ -408,7 +410,7 @@ object PartialFunction { * @param pf the PartialFunction[T, U] * @return `Some(pf(x))` if `pf isDefinedAt x`, `None` otherwise. */ - def condOpt[A, B](x: A)(pf: PartialFunction[A, B]): Option[B] = { + def condOpt[A, B](x: A)(pf: PartialFunction[A, B]^): Option[B] = { val z = pf.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(z)) Some(z) else None } diff --git a/library/src/scala/Short.scala b/library/src/scala/Short.scala index fc58ad8640e7..03b0929ea5ce 100644 --- a/library/src/scala/Short.scala +++ b/library/src/scala/Short.scala @@ -455,7 +455,7 @@ object Short extends AnyValCompanion { /** The largest value representable as a Short. */ final val MaxValue = java.lang.Short.MAX_VALUE - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToShort`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. * @@ -464,7 +464,7 @@ object Short extends AnyValCompanion { */ def box(x: Short): java.lang.Short = ??? - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Short. * diff --git a/library/src/scala/Unit.scala b/library/src/scala/Unit.scala index 1799f678e3fa..e7ad25073f50 100644 --- a/library/src/scala/Unit.scala +++ b/library/src/scala/Unit.scala @@ -31,7 +31,7 @@ final abstract class Unit private extends AnyVal { @scala.annotation.compileTimeOnly("`Unit` companion object is not allowed in source; instead, use `()` for the unit value") object Unit extends AnyValCompanion { - /** Transform a value type into a boxed reference type. + /** Transforms a value type into a boxed reference type. * * This method is not intended for use in source code. * The runtime representation of this value is platform specific. @@ -41,7 +41,7 @@ object Unit extends AnyValCompanion { */ def box(x: Unit): scala.runtime.BoxedUnit = scala.runtime.BoxedUnit.UNIT - /** Transform a boxed type into a value type. Note that this + /** Transforms a boxed type into a value type. Note that this * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a scala.runtime.BoxedUnit. * diff --git a/library/src/scala/caps/Pure.scala b/library/src/scala/caps/Pure.scala index 11d0e3f039e9..05f7e64f884d 100644 --- a/library/src/scala/caps/Pure.scala +++ b/library/src/scala/caps/Pure.scala @@ -7,5 +7,5 @@ import language.experimental.captureChecking * sense that their values retain no capabilities including capabilities needed * to perform effects. This has formal meaning only under capture checking. */ -trait Pure: +trait Pure extends Any: this: Pure => diff --git a/library/src/scala/collection/ArrayOps.scala b/library/src/scala/collection/ArrayOps.scala index c7f5ff67bd73..40570e5c261b 100644 --- a/library/src/scala/collection/ArrayOps.scala +++ b/library/src/scala/collection/ArrayOps.scala @@ -17,6 +17,8 @@ import scala.language.`2.13` 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 => _, booleanArrayOps => _, @@ -103,7 +105,7 @@ object ArrayOps { * @return a new array resulting from applying the given collection-valued function * `f` to each element of this array and concatenating the results. */ - def flatMap[B: ClassTag](f: A => IterableOnce[B]): Array[B] = { + def flatMap[B: ClassTag](f: A => IterableOnce[B]^): Array[B] = { val b = ArrayBuilder.make[B] var i = 0 while(i < xs.length) { @@ -118,7 +120,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) @@ -179,7 +181,7 @@ object ArrayOps { private final val MaxStableSortLength = 300 /** Avoid an allocation in [[collect]]. */ - private val fallback: Any => Any = _ => fallback + private val fallback: Any -> Any = _ => fallback } /** This class serves as a wrapper for `Array`s with many of the operations found in @@ -368,7 +370,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. */ @@ -587,7 +589,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @return an array consisting of the elements of this array * sorted according to the ordering `ord`. */ - def sorted[B >: A](implicit ord: Ordering[B]): Array[A] = { + def sorted[B >: A](implicit ord: Ordering[B]^): Array[A] = { val len = xs.length def boxed = if(len < ArrayOps.MaxStableSortLength) { val a = xs.clone() @@ -665,7 +667,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. * @@ -965,7 +967,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @return a new array resulting from applying the given collection-valued function * `f` to each element of this array and concatenating the results. */ - def flatMap[B : ClassTag](f: A => IterableOnce[B]): Array[B] = { + def flatMap[B : ClassTag](f: A => IterableOnce[B]^): Array[B] = { val b = ArrayBuilder.make[B] var i = 0 while(i < xs.length) { @@ -975,7 +977,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { b.result() } - def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = + def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B]^, m: ClassTag[B]): Array[B] = flatMap[B](x => asIterable(f(x))) /** Flattens a two-dimensional array by concatenating all its rows @@ -985,7 +987,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @param asIterable A function that converts elements of this array to rows - Iterables of type `B`. * @return An array obtained by concatenating rows of this array. */ - def flatten[B](implicit asIterable: A => IterableOnce[B], m: ClassTag[B]): Array[B] = { + def flatten[B](implicit asIterable: A => IterableOnce[B]^, m: ClassTag[B]): Array[B] = { val b = ArrayBuilder.make[B] val len = xs.length var size = 0 @@ -1018,7 +1020,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * `pf` to each element on which it is defined and collecting the results. * The order of the elements is preserved. */ - def collect[B: ClassTag](pf: PartialFunction[A, B]): Array[B] = { + def collect[B: ClassTag](pf: PartialFunction[A, B]^): Array[B] = { val fallback: Any => Any = ArrayOps.fallback val b = ArrayBuilder.make[B] var i = 0 @@ -1032,7 +1034,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { /** Finds the first element of the array for which the given partial function is defined, and applies the * partial function to it. */ - def collectFirst[B](@deprecatedName("f","2.13.9") pf: PartialFunction[A, B]): Option[B] = { + def collectFirst[B](@deprecatedName("f","2.13.9") pf: PartialFunction[A, B]^): Option[B] = { val fallback: Any => Any = ArrayOps.fallback var i = 0 while (i < xs.length) { @@ -1052,7 +1054,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @return a new array containing pairs consisting of corresponding elements of this array and `that`. * The length of the returned array is the minimum of the lengths of this array and `that`. */ - def zip[B](that: IterableOnce[B]): Array[(A, B)] = { + def zip[B](that: IterableOnce[B]^): Array[(A, B)] = { val b = new ArrayBuilder.ofRef[(A, B)]() val k = that.knownSize b.sizeHint(if(k >= 0) min(k, xs.length) else xs.length) @@ -1082,7 +1084,7 @@ final class ArrayOps[A](private val xs: Array[A]) 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[A, B, Array[A]] = new LazyZip2(xs, immutable.ArraySeq.unsafeWrapArray(xs), that) + def lazyZip[B](that: Iterable[B]^): LazyZip2[A, B, Array[A]]^{that} = new LazyZip2(xs, immutable.ArraySeq.unsafeWrapArray(xs), that) /** Returns an array formed from this array and another iterable collection * by combining corresponding elements in pairs. @@ -1097,7 +1099,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * If this array is shorter than `that`, `thisElem` values are used to pad the result. * If `that` is shorter than this array, `thatElem` values are used to pad the result. */ - def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): Array[(A1, B)] = { + def zipAll[A1 >: A, B](that: Iterable[B]^, thisElem: A1, thatElem: B): Array[(A1, B)] = { val b = new ArrayBuilder.ofRef[(A1, B)]() val k = that.knownSize b.sizeHint(max(k, xs.length)) @@ -1153,7 +1155,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { @`inline` final def +: [B >: A : ClassTag](x: B): Array[B] = prepended(x) /** A copy of this array with all elements of a collection prepended. */ - def prependedAll[B >: A : ClassTag](prefix: IterableOnce[B]): Array[B] = { + def prependedAll[B >: A : ClassTag](prefix: IterableOnce[B]^): Array[B] = { val b = ArrayBuilder.make[B] val k = prefix.knownSize if(k >= 0) b.sizeHint(k + xs.length) @@ -1170,12 +1172,12 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { dest } - @`inline` final def ++: [B >: A : ClassTag](prefix: IterableOnce[B]): Array[B] = prependedAll(prefix) + @`inline` final def ++: [B >: A : ClassTag](prefix: IterableOnce[B]^): Array[B] = prependedAll(prefix) @`inline` final def ++: [B >: A : ClassTag](prefix: Array[_ <: B]): Array[B] = prependedAll(prefix) /** A copy of this array with all elements of a collection appended. */ - def appendedAll[B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = { + def appendedAll[B >: A : ClassTag](suffix: IterableOnce[B]^): Array[B] = { val b = ArrayBuilder.make[B] b.sizeHint(suffix, delta = xs.length) b.addAll(xs) @@ -1190,15 +1192,15 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { dest } - @`inline` final def :++ [B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = appendedAll(suffix) + @`inline` final def :++ [B >: A : ClassTag](suffix: IterableOnce[B]^): Array[B] = appendedAll(suffix) @`inline` final def :++ [B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = appendedAll(suffix) - @`inline` final def concat[B >: A : ClassTag](suffix: IterableOnce[B]): Array[B] = appendedAll(suffix) + @`inline` final def concat[B >: A : ClassTag](suffix: IterableOnce[B]^): Array[B] = appendedAll(suffix) @`inline` final def concat[B >: A : ClassTag](suffix: Array[_ <: B]): Array[B] = appendedAll(suffix) - @`inline` final def ++[B >: A : ClassTag](xs: IterableOnce[B]): Array[B] = appendedAll(xs) + @`inline` final def ++[B >: A : ClassTag](xs: IterableOnce[B]^): Array[B] = appendedAll(xs) @`inline` final def ++[B >: A : ClassTag](xs: Array[_ <: B]): Array[B] = appendedAll(xs) @@ -1219,7 +1221,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @param other The patch values * @param replaced The number of values in the original array that are replaced by the patch. */ - def patch[B >: A : ClassTag](from: Int, other: IterableOnce[B], replaced: Int): Array[B] = { + def patch[B >: A : ClassTag](from: Int, other: IterableOnce[B]^, replaced: Int): Array[B] = { val b = ArrayBuilder.make[B] val k = other.knownSize val r = if(replaced < 0) 0 else replaced @@ -1347,7 +1349,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. @@ -1655,7 +1657,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @return `true` if the sequence `that` is contained in this array at * index `offset`, otherwise `false`. */ - def startsWith[B >: A](that: IterableOnce[B], offset: Int = 0): Boolean = mutable.ArraySeq.make(xs).startsWith(that, offset) + def startsWith[B >: A](that: IterableOnce[B]^, offset: Int = 0): Boolean = mutable.ArraySeq.make(xs).startsWith(that, offset) // we have another overload here, so we need to duplicate this method /** Tests whether this array ends with the given sequence. @@ -1663,5 +1665,5 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @param that the sequence to test * @return `true` if this array has `that` as a suffix, `false` otherwise. */ - def endsWith[B >: A](that: Iterable[B]): Boolean = mutable.ArraySeq.make(xs).endsWith(that) + def endsWith[B >: A](that: Iterable[B]^): Boolean = mutable.ArraySeq.make(xs).endsWith(that) } diff --git a/library/src/scala/collection/BitSet.scala b/library/src/scala/collection/BitSet.scala index 98beab6ae521..dc3d3b7ab7e7 100644 --- a/library/src/scala/collection/BitSet.scala +++ b/library/src/scala/collection/BitSet.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import java.io.{ObjectInputStream, ObjectOutputStream} import scala.annotation.nowarn @@ -33,8 +35,8 @@ import scala.collection.mutable.Builder * @define coll bitset * @define Coll `BitSet` */ -trait BitSet extends SortedSet[Int] with BitSetOps[BitSet] { - override protected def fromSpecific(coll: IterableOnce[Int]): BitSet = bitSetFactory.fromSpecific(coll) +trait BitSet extends SortedSet[Int] with BitSetOps[BitSet] { self: BitSet => + 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""") @@ -49,7 +51,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 { @@ -243,7 +245,7 @@ transparent trait BitSetOps[+C <: BitSet with BitSetOps[C]] coll.fromBitMaskNoCopy(a) } - override def concat(other: collection.IterableOnce[Int]): C = other match { + override def concat(other: collection.IterableOnce[Int]^): C = other match { case otherBitset: BitSet => val len = coll.nwords max otherBitset.nwords val words = new Array[Long](len) @@ -298,9 +300,9 @@ transparent trait BitSetOps[+C <: BitSet with BitSetOps[C]] */ def map(f: Int => Int): C = fromSpecific(new View.Map(this, f)) - def flatMap(f: Int => IterableOnce[Int]): C = fromSpecific(new View.FlatMap(this, f)) + def flatMap(f: Int => IterableOnce[Int]^): C = fromSpecific(new View.FlatMap(this, f)) - def collect(pf: PartialFunction[Int, Int]): C = fromSpecific(super[SortedSetOps].collect(pf)) + def collect(pf: PartialFunction[Int, Int]^): C = fromSpecific(super[SortedSetOps].collect(pf)) override def partition(p: Int => Boolean): (C, C) = { val left = filter(p) diff --git a/library/src/scala/collection/BufferedIterator.scala b/library/src/scala/collection/BufferedIterator.scala index e933ffcd4c16..4076b9662940 100644 --- a/library/src/scala/collection/BufferedIterator.scala +++ b/library/src/scala/collection/BufferedIterator.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking /** Buffered iterators are iterators which provide a method `head` * that inspects the next element without discarding it. diff --git a/library/src/scala/collection/BuildFrom.scala b/library/src/scala/collection/BuildFrom.scala index 1a623228db55..8ee65badf1a4 100644 --- a/library/src/scala/collection/BuildFrom.scala +++ b/library/src/scala/collection/BuildFrom.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.implicitNotFound import scala.collection.mutable.Builder import scala.collection.immutable.WrappedString @@ -27,7 +29,7 @@ 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^{it} /** 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. */ @@ -38,7 +40,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^{it} = self.fromSpecific(from)(it) def newBuilder: Builder[A, C] = self.newBuilder(from) } } @@ -49,42 +51,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]^{it} = View.from(it) def newBuilder(from: View[A]): Builder[B, View[B]] = View.newBuilder } @@ -98,12 +100,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] } } @@ -113,11 +115,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]^{it} = (from: IterableOps[A0, CC, _]).iterableFactory.from(it) } 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]^{it} = Iterator.from(it) } } diff --git a/library/src/scala/collection/DefaultMap.scala b/library/src/scala/collection/DefaultMap.scala index d957a4ef245e..08549fd8f975 100644 --- a/library/src/scala/collection/DefaultMap.scala +++ b/library/src/scala/collection/DefaultMap.scala @@ -14,6 +14,7 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking /** A default map which builds a default `immutable.Map` implementation for all * transformations. diff --git a/library/src/scala/collection/Factory.scala b/library/src/scala/collection/Factory.scala index 8e40f2955853..c46b29f73c5f 100644 --- a/library/src/scala/collection/Factory.scala +++ b/library/src/scala/collection/Factory.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.immutable.NumericRange import scala.language.implicitConversions import scala.collection.mutable.Builder @@ -30,14 +32,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 Any { self => /** * @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^{it} /** 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. */ @@ -49,7 +51,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() @@ -60,7 +62,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(it, delta = 0) b ++= it @@ -81,7 +83,7 @@ object Factory { * @define coll collection * @define Coll `Iterable` */ -trait IterableFactory[+CC[_]] extends Serializable { +trait IterableFactory[+CC[_]] extends Serializable, caps.Pure { /** Creates a target $coll from an existing source collection * @@ -89,7 +91,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 $coll * @tparam A the type of the ${coll}'s elements @@ -110,7 +112,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`. @@ -122,7 +124,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. * @@ -151,7 +153,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 @@ -159,7 +161,7 @@ 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]^{elem}) @uncheckedVariance]^{elem} = 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 @@ -168,7 +170,7 @@ 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]^{elem}]^{elem}) @uncheckedVariance]^{elem} = fill(n1)(fill(n2, n3)(elem)) /** 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 @@ -178,7 +180,7 @@ 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] = + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[(CC[CC[CC[A]^{elem}]^{elem}]^{elem}) @uncheckedVariance]^{elem} = fill(n1)(fill(n2, n3, n4)(elem)) /** Produces a five-dimensional $coll containing the results of some element computation a number of times. @@ -190,7 +192,7 @@ 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] = + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[(CC[CC[CC[CC[A]^{elem}]^{elem}]^{elem}]^{elem}) @uncheckedVariance]^{elem} = 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. @@ -198,7 +200,7 @@ trait IterableFactory[+CC[_]] extends Serializable { * @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 @@ -207,7 +209,7 @@ 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] = + def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[(CC[A]^{f}) @uncheckedVariance]^{f} = 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. @@ -218,7 +220,7 @@ 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] = + def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[(CC[CC[A]^{f}]^{f}) @uncheckedVariance]^{f} = 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. @@ -230,7 +232,7 @@ 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] = + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[(CC[CC[CC[A]^{f}]^{f}]^{f}) @uncheckedVariance]^{f} = 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. @@ -243,7 +245,7 @@ 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] = + 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]^{f}]^{f}]^{f}]^{f}) @uncheckedVariance]^{f} = tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) /** Concatenates all argument collections into a single $coll. @@ -272,13 +274,13 @@ 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]^{it} = factory.from[A](it) 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]^) = factory.from(it) def newBuilder(from: Any) = factory.newBuilder } @@ -286,7 +288,7 @@ 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] } } @@ -294,17 +296,17 @@ object IterableFactory { /** * @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]] & caps.Pure] extends IterableFactory[CC] { import SeqFactory.UnapplySeqWrapper final def unapplySeq[A](x: CC[A] @uncheckedVariance): UnapplySeqWrapper[A] = new UnapplySeqWrapper(x) // TODO is uncheckedVariance sound here? } object SeqFactory { @SerialVersionUID(3L) - class Delegate[CC[A] <: SeqOps[A, Seq, Seq[A]]](delegate: SeqFactory[CC]) extends SeqFactory[CC] { + class Delegate[CC[A] <: SeqOps[A, Seq, Seq[A]] & caps.Pure](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] } @@ -321,7 +323,7 @@ object SeqFactory { } } -trait StrictOptimizedSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends SeqFactory[CC] { +trait StrictOptimizedSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]] & caps.Pure] extends SeqFactory[CC] { override def fill[A](n: Int)(elem: => A): CC[A] = { val b = newBuilder[A] @@ -382,7 +384,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 { self => /** * An empty Map @@ -392,7 +394,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]^{it} /** * A collection of type Map that contains given key/value bindings. @@ -425,20 +427,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]^{it} = 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] { + class Delegate[C[_, _] <: caps.Pure](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 } @@ -455,9 +457,9 @@ object MapFactory { * @define coll collection * @define Coll `Iterable` */ -trait EvidenceIterableFactory[+CC[_], Ev[_]] extends Serializable { +trait EvidenceIterableFactory[+CC[_], Ev[_]] extends Serializable, caps.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] @@ -518,13 +520,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]^) = 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]^) = factory.from[A](it) def newBuilder(from: Any): Builder[A, CC[A]] = factory.newBuilder[A] } @@ -532,7 +534,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] } } @@ -669,7 +671,7 @@ object ClassTagIterableFactory { @SerialVersionUID(3L) class AnyIterableDelegate[CC[_]](delegate: ClassTagIterableFactory[CC]) extends IterableFactory[CC] { def empty[A]: CC[A] = delegate.empty(using ClassTag.Any).asInstanceOf[CC[A]] - def from[A](it: IterableOnce[A]): CC[A] = delegate.from[Any](it)(using ClassTag.Any).asInstanceOf[CC[A]] + def from[A](it: IterableOnce[A]^): CC[A] = delegate.from[Any](it)(using ClassTag.Any).asInstanceOf[CC[A]] def newBuilder[A]: Builder[A, CC[A]] = delegate.newBuilder(using ClassTag.Any).asInstanceOf[Builder[A, CC[A]]] override def apply[A](elems: A*): CC[A] = delegate.apply[Any](elems: _*)(using ClassTag.Any).asInstanceOf[CC[A]] override def iterate[A](start: A, len: Int)(f: A => A): CC[A] = delegate.iterate[A](start, len)(f)(using ClassTag.Any.asInstanceOf[ClassTag[A]]) @@ -697,7 +699,7 @@ object ClassTagSeqFactory { /** A SeqFactory that uses ClassTag.Any as the evidence for every element type. This may or may not be * sound depending on the use of the `ClassTag` by the collection implementation. */ @SerialVersionUID(3L) - class AnySeqDelegate[CC[A] <: SeqOps[A, Seq, Seq[A]]](delegate: ClassTagSeqFactory[CC]) + class AnySeqDelegate[CC[A] <: SeqOps[A, Seq, Seq[A]] & caps.Pure](delegate: ClassTagSeqFactory[CC]) extends ClassTagIterableFactory.AnyIterableDelegate[CC](delegate) with SeqFactory[CC] } @@ -734,11 +736,11 @@ trait StrictOptimizedClassTagSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extend * @define coll collection * @define Coll `Iterable` */ -trait SortedMapFactory[+CC[_, _]] extends Serializable { +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) @@ -765,20 +767,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/library/src/scala/collection/Hashing.scala b/library/src/scala/collection/Hashing.scala index 5ba8ad24948f..40850a524a40 100644 --- a/library/src/scala/collection/Hashing.scala +++ b/library/src/scala/collection/Hashing.scala @@ -14,6 +14,7 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking protected[collection] object Hashing { diff --git a/library/src/scala/collection/IndexedSeq.scala b/library/src/scala/collection/IndexedSeq.scala index 366fd526a022..fda8703f60a5 100644 --- a/library/src/scala/collection/IndexedSeq.scala +++ b/library/src/scala/collection/IndexedSeq.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{nowarn, tailrec} import scala.collection.Searching.{Found, InsertionPoint, SearchResult} import scala.collection.Stepper.EfficientSplit @@ -22,7 +24,8 @@ import scala.math.Ordering /** Base trait for indexed sequences that have efficient `apply` and `length` */ trait IndexedSeq[+A] extends Seq[A] with IndexedSeqOps[A, IndexedSeq, IndexedSeq[A]] - with IterableFactoryDefaults[A, IndexedSeq] { + with IterableFactoryDefaults[A, IndexedSeq] + with caps.Pure { @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix: String = "IndexedSeq" @@ -33,9 +36,9 @@ trait IndexedSeq[+A] extends Seq[A] object IndexedSeq extends SeqFactory.Delegate[IndexedSeq](immutable.IndexedSeq) /** Base trait for indexed Seq operations */ -transparent trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self => +transparent trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self: IndexedSeqOps[A, CC, C]^ => - def iterator: Iterator[A] = view.iterator + def iterator: Iterator[A]^{this} = view.iterator override def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S with EfficientSplit = { import convert.impl._ @@ -48,7 +51,7 @@ transparent trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C s.asInstanceOf[S with EfficientSplit] } - override def reverseIterator: Iterator[A] = view.reverseIterator + override def reverseIterator: Iterator[A]^{this} = view.reverseIterator /* TODO 2.14+ uncomment and delete related code in IterableOnce @tailrec private def foldl[B](start: Int, end: Int, z: B, op: (B, A) => B): B = @@ -68,33 +71,34 @@ transparent trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C //override def reduceRight[B >: A](op: (A, B) => B): B = if (length > 0) foldr(0, length - 1, apply(length - 1), op) else super.reduceRight(op) - override def view: IndexedSeqView[A] = new IndexedSeqView.Id[A](this) + override def view: IndexedSeqView[A]^{this} = new IndexedSeqView.Id[A](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 view(from: Int, until: Int): IndexedSeqView[A]^{this} = view.slice(from, until) - override protected def reversed: Iterable[A] = new IndexedSeqView.Reverse(this) + override protected def reversed: Iterable[A]^{this} = new IndexedSeqView.Reverse(this) // Override transformation operations to use more efficient views than the default ones - override def prepended[B >: A](elem: B): CC[B] = iterableFactory.from(new IndexedSeqView.Prepended(elem, this)) + override def prepended[B >: A](elem: B): CC[B]^{this} = iterableFactory.from(new IndexedSeqView.Prepended(elem, this)) - override def take(n: Int): C = fromSpecific(new IndexedSeqView.Take(this, n)) + override def take(n: Int): C^{this} = fromSpecific(new IndexedSeqView.Take(this, n)) - override def takeRight(n: Int): C = fromSpecific(new IndexedSeqView.TakeRight(this, n)) + override def takeRight(n: Int): C^{this} = fromSpecific(new IndexedSeqView.TakeRight(this, n)) - override def drop(n: Int): C = fromSpecific(new IndexedSeqView.Drop(this, n)) + override def drop(n: Int): C^{this} = fromSpecific(new IndexedSeqView.Drop(this, n)) - override def dropRight(n: Int): C = fromSpecific(new IndexedSeqView.DropRight(this, n)) + override def dropRight(n: Int): C^{this} = 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]^{this, f} = iterableFactory.from(new IndexedSeqView.Map(this, f)) - override def reverse: C = fromSpecific(new IndexedSeqView.Reverse(this)) + override def reverse: C^{this} = fromSpecific(new IndexedSeqView.Reverse(this)) - override def slice(from: Int, until: Int): C = fromSpecific(new IndexedSeqView.Slice(this, from, until)) + override def slice(from: Int, until: Int): C^{this} = fromSpecific(new IndexedSeqView.Slice(this, from, until)) - override def sliding(size: Int, step: Int): Iterator[C] = { + override def sliding(size: Int, step: Int): Iterator[C^{this}]^{this} = { require(size >= 1 && step >= 1, f"size=$size%d and step=$step%d, but both must be positive") - new IndexedSeqSlidingIterator[A, CC, C](this, size, step) + val it = new IndexedSeqSlidingIterator[A, CC, C](this, size, step) + it.asInstanceOf[Iterator[Nothing]] // TODO: seems like CC cannot figure this out yet } override def head: A = @@ -123,7 +127,7 @@ transparent trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C 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 @@ -153,8 +157,10 @@ transparent trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C } /** A fast sliding iterator for IndexedSeqs which uses the underlying `slice` operation. */ -private final class IndexedSeqSlidingIterator[A, CC[_], C](s: IndexedSeqOps[A, CC, C], size: Int, step: Int) - extends AbstractIterator[C] { +private final class IndexedSeqSlidingIterator[A, CC[_], C](s: IndexedSeqOps[A, CC, C]^, size: Int, step: Int) + extends AbstractIterator[C^{s}] { + // CC note: seems like the compiler cannot figure out that this class <: Iterator[C^{s}], + // so we need a cast when upcasting is needed. private[this] val len = s.length private[this] var pos = 0 @@ -165,7 +171,7 @@ private final class IndexedSeqSlidingIterator[A, CC[_], C](s: IndexedSeqOps[A, C def hasNext: Boolean = chklen && pos < len - def next(): C = if (!chklen || !hasNext) Iterator.empty.next() else { + def next(): C^{s} = if (!chklen || !hasNext) Iterator.empty.next() else { val end = { val x = pos + size; if (x < 0 || x > len) len else x } // (pos.toLong + size).min(len).toInt val slice = s.slice(pos, end) pos = diff --git a/library/src/scala/collection/IndexedSeqView.scala b/library/src/scala/collection/IndexedSeqView.scala index d03ff1b1c689..545563bb51a0 100644 --- a/library/src/scala/collection/IndexedSeqView.scala +++ b/library/src/scala/collection/IndexedSeqView.scala @@ -14,34 +14,36 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn /** 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 IndexedSeqOps[A, View, View[A]] with SeqView[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, suffix} = new IndexedSeqView.Concat(this, suffix) + def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]^): IndexedSeqView[B]^{this, suffix} = new IndexedSeqView.Concat(this, suffix) + def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]^): IndexedSeqView[B]^{this, prefix} = new IndexedSeqView.Concat(prefix, this) @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix: String = "IndexedSeqView" @@ -50,7 +52,7 @@ 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 { private[this] var current = 0 private[this] var remainder = self.length override def knownSize: Int = remainder @@ -64,7 +66,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) @@ -72,7 +74,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 @@ -84,7 +86,7 @@ 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 { private[this] var remainder = self.length private[this] var pos = remainder - 1 @inline private[this] def _hasNext: Boolean = remainder > 0 @@ -99,7 +101,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 @@ -122,51 +124,51 @@ object IndexedSeqView { type SomeIndexedSeqOps[A] = IndexedSeqOps[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] { - override def reverse: IndexedSeqView[A] = underlying match { + class Reverse[A](underlying: SomeIndexedSeqOps[A]^) extends SeqView.Reverse[A](underlying) with IndexedSeqView[A] { + override def reverse: IndexedSeqView[A]^{this} = underlying match { case x: IndexedSeqView[A] => x case _ => super.reverse } } @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/library/src/scala/collection/Iterable.scala b/library/src/scala/collection/Iterable.scala index 641b4bb4745e..eac89341d8ba 100644 --- a/library/src/scala/collection/Iterable.scala +++ b/library/src/scala/collection/Iterable.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn import scala.annotation.unchecked.uncheckedVariance import scala.collection.mutable.Builder @@ -95,7 +97,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 @@ -138,24 +140,24 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w */ // 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`. @@ -175,7 +177,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * `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. * @@ -252,7 +254,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w 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 +303,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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(caps.unsafe.unsafeAssumePure(this) /* see comment in SizeCompareOps*/) /** Compares the size of this $coll to the size of another `Iterable`. * @@ -317,7 +319,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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 +344,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w /** 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,9 +380,9 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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 +419,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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. @@ -428,15 +430,15 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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, isFlipped = false) val second = new View.Filter(this, p, isFlipped = 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 @@ -445,7 +447,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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 @@ -453,11 +455,11 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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 @@ -466,9 +468,9 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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` @@ -477,7 +479,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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" @@ -499,7 +501,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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`). @@ -520,11 +522,11 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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))` */ - 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) } @@ -532,12 +534,12 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w /** 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. @@ -647,9 +649,9 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * * @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. @@ -667,7 +669,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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 @@ -681,13 +683,13 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w 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 @@ -711,9 +713,9 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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]^{this, f} = new LeftPartitionMapped(this, f) + val right: View[A2]^{this, f} = new RightPartitionMapped(this, f) (iterableFactory.from(left), iterableFactory.from(right)) } @@ -726,7 +728,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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 { + def concat[B >: A](suffix: IterableOnce[B]^): CC[B]^{this, suffix} = iterableFactory.from { suffix match { case suffix: Iterable[B] => new View.Concat(this, suffix) case suffix => iterator ++ suffix.iterator @@ -734,7 +736,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w } /** 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 $ccoll formed from this $coll and another iterable collection * by combining corresponding elements in pairs. @@ -745,12 +747,12 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @return a new $ccoll 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. @@ -766,7 +768,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * 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. @@ -787,9 +789,9 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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)) } @@ -814,10 +816,10 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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)) } @@ -828,7 +830,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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 @@ -839,12 +841,12 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w * @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 @@ -853,7 +855,7 @@ transparent trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] w } @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 }) @@ -867,6 +869,13 @@ object IterableOps { * [[scala.collection.IterableOps!.sizeCompare(Int):Int* `sizeCompare(Int)`]] */ final class SizeCompareOps private[collection](val it: IterableOps[_, AnyConstr, _]) extends AnyVal { + // CC Problem: if we add the logically needed `^`s to the `it` parameter and the + // self type, separation checking fails in the compiler-generated equals$extends + // method of the value class. There seems to be something wrong how pattern + // matching interacts with separation checking. A minimized test case + // is pending/pos-custom-args/captures/SizeCompareOps-redux.scala. + // Without the `^`s, the `sizeIs` method needs an unsafeAssumePure. + /** 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. */ @@ -891,22 +900,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)) } @@ -926,7 +935,7 @@ object Iterable extends IterableFactory.Delegate[Iterable](immutable.Iterable) { override def view: View.Single[A] = 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 drop(n: Int): Iterable[A] = 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 @@ -944,7 +953,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 @@ -962,7 +971,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 } @@ -984,11 +993,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)(using ordering) + override protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]^): CC[A @uncheckedVariance] = sortedIterableFactory.from(coll)(using ordering) override protected def newSpecificBuilder: mutable.Builder[A @uncheckedVariance, CC[A @uncheckedVariance]] = sortedIterableFactory.newBuilder[A](using ordering) override def empty: CC[A @uncheckedVariance] = sortedIterableFactory.empty(using 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) } @@ -1008,7 +1017,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) @@ -1016,7 +1026,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,13 +1045,13 @@ trait MapFactoryDefaults[K, +V, trait SortedMapFactoryDefaults[K, +V, +CC[x, y] <: Map[x, y] with SortedMapOps[x, y, CC, CC[x, y]] with UnsortedCC[x, y], +WithFilterCC[x] <: IterableOps[x, WithFilterCC, WithFilterCC[x]] with Iterable[x], - +UnsortedCC[x, y] <: Map[x, y]] extends SortedMapOps[K, V, CC, CC[K, V @uncheckedVariance]] with MapOps[K, V, UnsortedCC, CC[K, V @uncheckedVariance]] { + +UnsortedCC[x, y] <: Map[x, y]] extends SortedMapOps[K, V, CC, CC[K, V @uncheckedVariance]] with MapOps[K, V, UnsortedCC, CC[K, V @uncheckedVariance]] with caps.Pure { self: IterableOps[(K, V), WithFilterCC, _] => override def empty: CC[K, V @uncheckedVariance] = sortedMapFactory.empty(using ordering) - override protected def fromSpecific(coll: IterableOnce[(K, V @uncheckedVariance)]): CC[K, V @uncheckedVariance] = sortedMapFactory.from(coll)(using ordering) + override protected def fromSpecific(coll: IterableOnce[(K, V @uncheckedVariance)]^): CC[K, V @uncheckedVariance] = sortedMapFactory.from(coll)(using ordering) override protected def newSpecificBuilder: mutable.Builder[(K, V @uncheckedVariance), CC[K, V @uncheckedVariance]] = sortedMapFactory.newBuilder[K, V](using 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/library/src/scala/collection/IterableOnce.scala b/library/src/scala/collection/IterableOnce.scala index 44a5eaa1ca20..e750d955e8fb 100644 --- a/library/src/scala/collection/IterableOnce.scala +++ b/library/src/scala/collection/IterableOnce.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance import scala.collection.mutable.StringBuilder @@ -43,7 +45,7 @@ import scala.runtime.{AbstractFunction1, AbstractFunction2} * @define coll collection * @define ccoll $coll */ -trait IterableOnce[+A] extends Any { +trait IterableOnce[+A] extends Any { this: IterableOnce[A]^ => /** An [[scala.collection.Iterator]] over the elements of this $coll. * @@ -51,7 +53,7 @@ trait IterableOnce[+A] extends Any { * in its current state, but if it is an [[scala.collection.Iterable]], this method always returns a new * [[scala.collection.Iterator]]. */ - def iterator: Iterator[A] + def iterator: Iterator[A]^{this} /** Returns a [[scala.collection.Stepper]] for the elements of this collection. * @@ -73,9 +75,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[_]](implicit shape: StepperShape[A, S]): S^{this} = { 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]]) @@ -92,7 +94,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) @@ -110,7 +112,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) @@ -128,7 +130,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 @@ -137,10 +139,10 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext def forall(f: A => Boolean): Boolean = it.iterator.forall(f) @deprecated("Use .iterator.collectFirst(...) instead", "2.13.0") - def collectFirst[B](f: PartialFunction[A, B]): Option[B] = it.iterator.collectFirst(f) + 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) @@ -246,13 +248,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 { - case it: Iterable[A] => it.map(f) + def map[B](f: A => B): IterableOnce[B]^{f} = it match { + case it: Iterable[A]^{f} => 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) } @@ -277,7 +279,7 @@ 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], + @inline private[collection] def copyElemsToArray[A, B >: A](elems: IterableOnce[A]^, xs: Array[B], start: Int = 0, len: Int = Int.MaxValue): Int = @@ -321,7 +323,7 @@ object IterableOnce { * @define exactlyOnce * Each element appears exactly once in the computation. */ -transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => +transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => /////////////////////////////////////////////////////////////// Abstract methods that must be implemented /** Produces a $coll containing cumulative results of applying the @@ -335,7 +337,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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. * @@ -343,7 +345,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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. * @@ -351,7 +353,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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(pred: A => Boolean): C^{this, pred} /** Selects the first `n` elements. * $orderDependent @@ -360,7 +362,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * 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} /** Selects the longest prefix of elements that satisfy a predicate. * @@ -386,7 +388,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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 the first `n` ones. * $orderDependent @@ -395,7 +397,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * 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} /** Selects all elements except the longest prefix that satisfies a predicate. * @@ -422,7 +424,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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: @@ -437,7 +439,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * 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 $ccoll by applying a function to all elements of this $coll. * @@ -446,7 +448,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @return a new $ccoll 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 $ccoll by applying a function to all elements of this $coll * and using the elements of the resulting collections. @@ -479,7 +481,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @return a new $ccoll 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} /** Given that the elements of this collection are themselves iterable collections, * converts this $coll into a $ccoll comprising the elements of these iterable collections. @@ -506,7 +508,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * type of this $coll is an `Iterable`. * @return a new $ccoll resulting from concatenating all element collections. */ - def flatten[B](implicit asIterable: A => IterableOnce[B]): CC[B] + def flatten[B](implicit asIterable: A -> IterableOnce[B]): CC[B]^{this} /** Builds a new $ccoll by applying a partial function to all elements of this $coll * on which the function is defined. @@ -517,7 +519,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * `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. * @@ -526,7 +528,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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. * @@ -539,7 +541,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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. * @@ -551,7 +553,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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 } @@ -569,7 +571,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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 @@ -911,7 +913,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn 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) @@ -1154,13 +1156,13 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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]] { + 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 @@ -1193,7 +1195,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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 @@ -1210,7 +1212,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @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 @@ -1227,7 +1229,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * 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 @@ -1244,7 +1246,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * value for which it is defined, or `None` if none exists. * @example `Seq("a", 1, 5L).collectFirst({ case x: Int => x*10 }) = Some(10)` */ - def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = { + def collectFirst[B](pf: PartialFunction[A, B]^): Option[B] = { // Presumably the fastest way to get in and out of a partial function is for a sentinel function to return itself // (Tested to be lower-overhead than runWith. Would be better yet to not need to (formally) allocate it) val sentinel: scala.Function1[A, Any] = new AbstractFunction1[A, Any] { @@ -1286,7 +1288,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * `p(x, y)` is `true` for all corresponding elements `x` of this iterator * and `y` of `that`, otherwise `false` */ - def corresponds[B](that: IterableOnce[B])(p: (A, B) => Boolean): Boolean = { + def corresponds[B](that: IterableOnce[B]^)(p: (A, B) => Boolean): Boolean = { val a = iterator val b = that.iterator @@ -1433,10 +1435,10 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * xs.to(BitSet) // for xs: Iterable[Int] * }}} */ - def to[C1](factory: Factory[A, C1]): C1 = factory.fromSpecific(this) + def to[C1](factory: Factory[A, C1]): C1^{this} = 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 /** Converts this $coll to a `List`. * @@ -1485,7 +1487,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn * @tparam B The type of elements of the result, a supertype of `A`. * @return This $coll as a `Buffer[B]`. */ - @inline final def toBuffer[B >: A]: mutable.Buffer[B] = mutable.Buffer.from(this) + @inline final def toBuffer[B >: A]: mutable.Buffer[B] = caps.unsafe.unsafeAssumePure(mutable.Buffer.from(this)) // TODO will go away when buffer is fixed /** Converts this $coll to an `Array`. * @@ -1504,7 +1506,7 @@ transparent trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOn else mutable.ArrayBuilder.make[B].addAll(this).result() // For internal use - protected def reversed: Iterable[A] = { + protected def reversed: Iterable[A]^{this} = { var xs: immutable.List[A] = immutable.Nil val it = iterator while (it.hasNext) xs = it.next() :: xs diff --git a/library/src/scala/collection/Iterator.scala b/library/src/scala/collection/Iterator.scala index 4fb1cc6d362b..6a6132990f76 100644 --- a/library/src/scala/collection/Iterator.scala +++ b/library/src/scala/collection/Iterator.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.mutable.{ArrayBuffer, ArrayBuilder, Builder, ImmutableBuilder} import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance @@ -72,7 +74,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. * @@ -118,10 +121,11 @@ 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 + def head: A = { if (!hdDefined) { hd = next() @@ -154,7 +158,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") @@ -163,7 +167,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] @@ -186,7 +190,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 @@ -292,7 +296,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 = { @@ -322,7 +326,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) } @@ -342,7 +346,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 @@ -378,13 +382,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 @@ -413,7 +417,7 @@ 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, op} = ArrayBuffer.from(this).scanRight(z)(op).iterator /** Finds index of the first element satisfying some predicate after or at some start index. * @@ -476,11 +480,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 @@ -514,9 +518,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 = _ @@ -552,7 +556,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 @@ -564,7 +568,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 @@ -589,14 +593,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 @@ -630,19 +634,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]^{this, 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() @@ -653,9 +657,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 @@ -691,7 +695,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 @@ -790,10 +794,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 @@ -804,14 +808,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 @@ -828,7 +832,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 @@ -846,7 +850,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite * @tparam B the type of the elements of collection `that`. * @return `true` if both collections contain equal elements in the same order, `false` otherwise. */ - def sameElements[B >: A](that: IterableOnce[B]): Boolean = { + def sameElements[B >: A](that: IterableOnce[B]^): Boolean = { val those = that.iterator while (hasNext) { if (!those.hasNext) return false @@ -868,7 +872,7 @@ 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 class Partner extends AbstractIterator[A] { @@ -912,7 +916,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` @@ -952,7 +956,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() = { @@ -989,7 +993,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 @@ -1020,7 +1024,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 @@ -1035,7 +1039,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 @@ -1108,7 +1112,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 @@ -1130,7 +1134,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. @@ -1138,7 +1142,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 } @@ -1146,7 +1150,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 @uncheckedVariance]^) 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 @@ -1162,7 +1167,7 @@ object Iterator extends IterableFactory[Iterator] { // If we advanced the current iterator to a ConcatIterator, merge it into this one @tailrec def merge(): Unit = if (current.isInstanceOf[ConcatIterator[_]]) { - val c = current.asInstanceOf[ConcatIterator[A]] + val c = current.asInstanceOf[ConcatIterator[A]^{from}] current = c.current currentHasNextChecked = c.currentHasNextChecked if (c.tail != null) { @@ -1202,7 +1207,7 @@ object Iterator extends IterableFactory[Iterator] { current.next() } else Iterator.empty.next() - override def concat[B >: A](that: => IterableOnce[B]): Iterator[B] = { + override def concat[B >: A](that: => IterableOnce[B]^): Iterator[B]^{this, that} = { val c = new ConcatIteratorCell[B](that, null).asInstanceOf[ConcatIteratorCell[A]] if (tail == null) { tail = c @@ -1217,14 +1222,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 } /** 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 @@ -1255,7 +1260,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]^{this} = { val lo = from max 0 def adjustedBound = if (unbounded) -1 diff --git a/library/src/scala/collection/JavaConverters.scala b/library/src/scala/collection/JavaConverters.scala index b49e472c04b2..8d1503200188 100644 --- a/library/src/scala/collection/JavaConverters.scala +++ b/library/src/scala/collection/JavaConverters.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.{concurrent => juc} import java.{lang => jl, util => ju} diff --git a/library/src/scala/collection/LazyZipOps.scala b/library/src/scala/collection/LazyZipOps.scala index dba5b6432def..9a7dc3173926 100644 --- a/library/src/scala/collection/LazyZipOps.scala +++ b/library/src/scala/collection/LazyZipOps.scala @@ -14,6 +14,7 @@ package scala.collection import scala.language.`2.13` import scala.language.implicitConversions +import language.experimental.captureChecking /** Decorator representing lazily zipped pairs. * @@ -22,7 +23,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. @@ -32,11 +33,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 = { + def map[B, C](f: (El1, El2) => B)(implicit bf: BuildFrom[C1, B, C]): C^{this, f} = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator: AbstractIterator[B]^{this, f} = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator def hasNext = elems1.hasNext && elems2.hasNext @@ -47,12 +48,12 @@ 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 = { + def flatMap[B, C](f: (El1, El2) => Iterable[B]^)(implicit bf: BuildFrom[C1, B, C]): C^{this, f} = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator: AbstractIterator[B]^{this, f} = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator - private[this] var _current: Iterator[B] = Iterator.empty + private[this] var _current: Iterator[B]^{this, f} = Iterator.empty private def current = { while (!_current.hasNext && elems1.hasNext && elems2.hasNext) _current = f(elems1.next(), elems2.next()).iterator @@ -66,9 +67,9 @@ 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 = { + def filter[C](p: (El1, El2) => Boolean)(implicit bf: BuildFrom[C1, (El1, El2), C]): C^{this, p} = { bf.fromSpecific(src)(new AbstractView[(El1, El2)] { - def iterator: AbstractIterator[(El1, El2)] = new AbstractIterator[(El1, El2)] { + def iterator: AbstractIterator[(El1, El2)]^{this, p} = new AbstractIterator[(El1, El2)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] var _current: (El1, El2) = _ @@ -113,8 +114,8 @@ final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterabl while (elems1.hasNext && elems2.hasNext) f(elems1.next(), elems2.next()) } - private def toIterable: View[(El1, El2)] = new AbstractView[(El1, El2)] { - def iterator: AbstractIterator[(El1, El2)] = new AbstractIterator[(El1, El2)] { + private def toIterable: View[(El1, El2)]^{this} = new AbstractView[(El1, El2)] { + def iterator: AbstractIterator[(El1, El2)]^{this} = new AbstractIterator[(El1, El2)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator def hasNext = elems1.hasNext && elems2.hasNext @@ -136,7 +137,7 @@ final class LazyZip2[+El1, +El2, C1] private[collection](src: C1, coll1: Iterabl } object LazyZip2 { - implicit def lazyZip2ToIterable[El1, El2](zipped2: LazyZip2[El1, El2, _]): View[(El1, El2)] = zipped2.toIterable + implicit def lazyZip2ToIterable[El1, El2](zipped2: LazyZip2[El1, El2, _]^): View[(El1, El2)]^{zipped2} = zipped2.toIterable } @@ -148,9 +149,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. @@ -160,11 +161,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 = { + def map[B, C](f: (El1, El2, El3) => B)(implicit bf: BuildFrom[C1, B, C]): C^{this, f} = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator: AbstractIterator[B]^{this, f} = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -176,13 +177,13 @@ 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 = { + def flatMap[B, C](f: (El1, El2, El3) => Iterable[B]^)(implicit bf: BuildFrom[C1, B, C]): C^{this, f} = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator: AbstractIterator[B]^{this, f} = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator - private[this] var _current: Iterator[B] = Iterator.empty + private[this] var _current: Iterator[B]^{this, f} = Iterator.empty private def current = { while (!_current.hasNext && elems1.hasNext && elems2.hasNext && elems3.hasNext) _current = f(elems1.next(), elems2.next(), elems3.next()).iterator @@ -196,9 +197,9 @@ 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 = { + def filter[C](p: (El1, El2, El3) => Boolean)(implicit bf: BuildFrom[C1, (El1, El2, El3), C]): C^{this, p} = { bf.fromSpecific(src)(new AbstractView[(El1, El2, El3)] { - def iterator: AbstractIterator[(El1, El2, El3)] = new AbstractIterator[(El1, El2, El3)] { + def iterator: AbstractIterator[(El1, El2, El3)]^{this, p} = new AbstractIterator[(El1, El2, El3)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -249,8 +250,8 @@ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, f(elems1.next(), elems2.next(), elems3.next()) } - private def toIterable: View[(El1, El2, El3)] = new AbstractView[(El1, El2, El3)] { - def iterator: AbstractIterator[(El1, El2, El3)] = new AbstractIterator[(El1, El2, El3)] { + private def toIterable: View[(El1, El2, El3)]^{this} = new AbstractView[(El1, El2, El3)] { + def iterator: AbstractIterator[(El1, El2, El3)]^{this} = new AbstractIterator[(El1, El2, El3)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -276,7 +277,7 @@ final class LazyZip3[+El1, +El2, +El3, C1] private[collection](src: C1, } object LazyZip3 { - implicit def lazyZip3ToIterable[El1, El2, El3](zipped3: LazyZip3[El1, El2, El3, _]): View[(El1, El2, El3)] = zipped3.toIterable + implicit def lazyZip3ToIterable[El1, El2, El3](zipped3: LazyZip3[El1, El2, El3, _]^): View[(El1, El2, El3)]^{zipped3} = zipped3.toIterable } @@ -289,14 +290,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 = { + def map[B, C](f: (El1, El2, El3, El4) => B)(implicit bf: BuildFrom[C1, B, C]): C^{this, f} = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator: AbstractIterator[B]^{this, f} = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator @@ -309,14 +310,14 @@ 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 = { + def flatMap[B, C](f: (El1, El2, El3, El4) => Iterable[B]^)(implicit bf: BuildFrom[C1, B, C]): C^{this, f} = { bf.fromSpecific(src)(new AbstractView[B] { - def iterator: AbstractIterator[B] = new AbstractIterator[B] { + def iterator: AbstractIterator[B]^{this, f} = new AbstractIterator[B] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator private[this] val elems3 = coll3.iterator private[this] val elems4 = coll4.iterator - private[this] var _current: Iterator[B] = Iterator.empty + private[this] var _current: Iterator[B]^{this, f} = Iterator.empty private def current = { while (!_current.hasNext && elems1.hasNext && elems2.hasNext && elems3.hasNext && elems4.hasNext) _current = f(elems1.next(), elems2.next(), elems3.next(), elems4.next()).iterator @@ -330,9 +331,9 @@ 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 = { + def filter[C](p: (El1, El2, El3, El4) => Boolean)(implicit bf: BuildFrom[C1, (El1, El2, El3, El4), C]): C^{this, p} = { bf.fromSpecific(src)(new AbstractView[(El1, El2, El3, El4)] { - def iterator: AbstractIterator[(El1, El2, El3, El4)] = new AbstractIterator[(El1, El2, El3, El4)] { + def iterator: AbstractIterator[(El1, El2, El3, El4)]^{this, p} = 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, f(elems1.next(), elems2.next(), elems3.next(), elems4.next()) } - private def toIterable: View[(El1, El2, El3, El4)] = new AbstractView[(El1, El2, El3, El4)] { + private def toIterable: View[(El1, El2, El3, El4)]^{this} = new AbstractView[(El1, El2, El3, El4)] { def iterator: AbstractIterator[(El1, El2, El3, El4)] = new AbstractIterator[(El1, El2, El3, El4)] { private[this] val elems1 = coll1.iterator private[this] val elems2 = coll2.iterator @@ -418,6 +419,6 @@ final class LazyZip4[+El1, +El2, +El3, +El4, C1] private[collection](src: C1, } object LazyZip4 { - implicit def lazyZip4ToIterable[El1, El2, El3, El4](zipped4: LazyZip4[El1, El2, El3, El4, _]): View[(El1, El2, El3, El4)] = + implicit def lazyZip4ToIterable[El1, El2, El3, El4](zipped4: LazyZip4[El1, El2, El3, El4, _]^): View[(El1, El2, El3, El4)]^{zipped4} = zipped4.toIterable } diff --git a/library/src/scala/collection/LinearSeq.scala b/library/src/scala/collection/LinearSeq.scala index f6ae57168fcd..4c79575a22a8 100644 --- a/library/src/scala/collection/LinearSeq.scala +++ b/library/src/scala/collection/LinearSeq.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{nowarn, tailrec} /** Base trait for linearly accessed sequences that have efficient `head` and @@ -33,7 +35,7 @@ trait LinearSeq[+A] extends Seq[A] object LinearSeq extends SeqFactory.Delegate[LinearSeq](immutable.LinearSeq) /** Base trait for linear Seq operations */ -transparent trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeqOps[A, CC, C]] extends Any with SeqOps[A, CC, C] { +transparent trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] with LinearSeqOps[A, CC, C]] extends Any with SeqOps[A, CC, C] with caps.Pure { self => /** @inheritdoc * @@ -97,7 +99,7 @@ transparent trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] wi 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 @@ -187,7 +189,7 @@ transparent trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] wi 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) { @@ -260,7 +262,7 @@ transparent trait LinearSeqOps[+A, +CC[X] <: LinearSeq[X], +C <: LinearSeq[A] wi } } -transparent 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] { +transparent 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] { self => // 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/library/src/scala/collection/Map.scala b/library/src/scala/collection/Map.scala index 4d448f96c7cb..f2dd799b07e5 100644 --- a/library/src/scala/collection/Map.scala +++ b/library/src/scala/collection/Map.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn import scala.collection.generic.DefaultSerializable import scala.collection.mutable.StringBuilder @@ -24,7 +26,8 @@ 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 caps.Pure { def mapFactory: scala.collection.MapFactory[Map] = Map @@ -101,9 +104,9 @@ trait Map[K, +V] // erase CC to IterableOps instead of Object transparent trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] extends IterableOps[(K, V), Iterable, C] - with PartialFunction[K, V] { + with PartialFunction[K, V] { self: 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 = { @@ -132,7 +135,7 @@ transparent 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]^{it} = mapFactory.from(it) /** The companion object of this map, providing various factory methods. * @@ -190,21 +193,37 @@ transparent trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * * @return a set representing the keys contained by this map */ - def keySet: Set[K] = new KeySet + def keySet: Set[K] = + // If we know one of the strict implementations inside this library, simply return LazyKeySet + import MapOps.LazyKeySet + this match + case s: SeqMap[K, V] => new LazyKeySet(s) + case s: SortedMap[K, V] => new LazyKeySet(s) + case s: immutable.MapOps[K, V, immutable.Map, immutable.Map[K, V]] => new LazyKeySet(s) + case s: mutable.MapOps[K, V, mutable.Map, mutable.Map[K, V]] => new LazyKeySet(s) + case _ => new KeySet /** The implementation class of the set returned by `keySet`. */ protected class KeySet extends AbstractSet[K] with GenKeySet with DefaultSerializable { - def diff(that: Set[K]): Set[K] = fromSpecific(this.view.filterNot(that)) + // If you need a generic, capturing KeySet, create a View from keysIterator + def diff(that: Set[K]): Set[K] = fromSpecific(allKeys.filterNot(that)) } - /** A generic trait that is reused by keyset implementations */ + /** A generic trait that is reused by keyset implementations. + * Note that this version of KeySet copies all the keys into an interval val. + * See [[MapOps.LazyKeySet]] for a version that lazily captures the map. + */ protected trait GenKeySet { this: Set[K] => - def iterator: Iterator[K] = MapOps.this.keysIterator - def contains(key: K): Boolean = MapOps.this.contains(key) - override def size: Int = MapOps.this.size - override def knownSize: Int = MapOps.this.knownSize - override def isEmpty: Boolean = MapOps.this.isEmpty + // CC note: this is unavoidable to make the KeySet pure. + private[MapOps] val allKeys = MapOps.this.keysIterator.toSet + // We restore the lazy behavior in LazyKeySet + def iterator: Iterator[K] = + allKeys.iterator + def contains(key: K): Boolean = allKeys.contains(key) + override def size: Int = allKeys.size + override def knownSize: Int = allKeys.knownSize + override def isEmpty: Boolean = allKeys.isEmpty } /** An [[Iterable]] collection of the keys contained by this map. @@ -218,22 +237,22 @@ transparent trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * @return an [[Iterable]] collection of the keys contained by this map */ @deprecatedOverriding("This method should be an alias for keySet", since="2.13.13") - def keys: Iterable[K] = keySet + def keys: Iterable[K]^{this} = this.keySet /** Collects all values of this map in an iterable collection. * * @return the values of this map as an iterable. */ - def values: Iterable[V] = new AbstractIterable[V] with DefaultSerializable { + def values: Iterable[V]^{this} = new AbstractIterable[V] with DefaultSerializable { override def knownSize: Int = MapOps.this.knownSize - override def iterator: Iterator[V] = valuesIterator + override def iterator: Iterator[V]^{self} = valuesIterator } /** An [[Iterator]] of the keys contained by this map. * * @return an [[Iterator]] of the keys contained by this map */ - def keysIterator: Iterator[K] = new AbstractIterator[K] { + def keysIterator: Iterator[K]^{this} = new AbstractIterator[K] { val iter = MapOps.this.iterator def hasNext = iter.hasNext def next() = iter.next()._1 @@ -243,7 +262,7 @@ transparent trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * * @return an iterator over all values that are associated with some key in this map. */ - def valuesIterator: Iterator[V] = new AbstractIterator[V] { + def valuesIterator: Iterator[V]^{this} = new AbstractIterator[V] { val iter = MapOps.this.iterator def hasNext = iter.hasNext def next() = iter.next()._2 @@ -266,7 +285,7 @@ transparent 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. @@ -274,7 +293,7 @@ transparent 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. @@ -312,7 +331,7 @@ transparent trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * @return a new $coll resulting from applying the given function * `f` to each element of this $coll and collecting the results. */ - def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = mapFactory.from(new View.Map(this, f)) + def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2]^{this, f} = mapFactory.from(new View.Map(this, f)) /** Builds a new collection by applying a partial function to all elements of this $coll * on which the function is defined. @@ -324,7 +343,7 @@ transparent trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * `pf` to each element on which it is defined and collecting the results. * The order of the elements is preserved. */ - def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]): CC[K2, V2] = + def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]^): CC[K2, V2]^{this, pf} = mapFactory.from(new View.Collect(this, pf)) /** Builds a new map by applying a function to all elements of this $coll @@ -334,7 +353,7 @@ transparent 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]^{this, f} = 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 @@ -344,7 +363,7 @@ transparent 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]^{this, suffix} = mapFactory.from(suffix match { case it: Iterable[(K, V2)] => new View.Concat(this, it) case _ => iterator.concat(suffix.iterator) }) @@ -352,28 +371,28 @@ transparent 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]^{this, xs} = 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) @deprecated("Consider requiring an immutable Map or fall back to Map.concat.", "2.13.0") - def + [V1 >: V](kv: (K, V1)): CC[K, V1] = + def + [V1 >: V](kv: (K, V1)): CC[K, V1]^{this} = mapFactory.from(new View.Appended(this, kv)) @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") - def + [V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): CC[K, V1] = + def + [V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): CC[K, V1]^{this} = 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^{this, keys} = { lazy val keysSet = keys.iterator.to(immutable.Set) fromSpecific(this.view.filterKeys(k => !keysSet.contains(k))) } @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]^{this, that} = { + val thatIterable: Iterable[(K, V1)]^{that} = that match { case that: Iterable[(K, V1)] => that case that => View.from(that) } @@ -389,21 +408,32 @@ 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)) } + + /** The implementation class of the set returned by `keySet`, for pure maps. + */ + private class LazyKeySet[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C](mp: MapOps[K, V, CC, C]) extends AbstractSet[K] with DefaultSerializable { + def iterator: Iterator[K] = mp.keysIterator + def diff(that: Set[K]): Set[K] = LazyKeySet.this.fromSpecific(this.view.filterNot(that)) + def contains(key: K): Boolean = mp.contains(key) + override def size: Int = mp.size + override def knownSize: Int = mp.knownSize + override def isEmpty: Boolean = mp.isEmpty + } } /** diff --git a/library/src/scala/collection/MapView.scala b/library/src/scala/collection/MapView.scala index a058f3f79514..5ede734455b3 100644 --- a/library/src/scala/collection/MapView.scala +++ b/library/src/scala/collection/MapView.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn import scala.collection.MapView.SomeMapOps import scala.collection.mutable.Builder @@ -21,7 +23,7 @@ trait MapView[K, +V] extends MapOps[K, V, ({ type l[X, Y] = View[(X, Y)] })#l, View[(K, V)]] with View[(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. @@ -29,42 +31,42 @@ trait MapView[K, +V] * @return the keys of this map as a view. */ @nowarn("msg=overriding method keys") - 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, isFlipped = false, pred) + override def filter(pred: ((K, V)) => Boolean): MapView[K, V]^{this, pred} = new MapView.Filter(this, isFlipped = false, pred) - override def filterNot(pred: ((K, V)) => Boolean): MapView[K, V] = new MapView.Filter(this, isFlipped = true, pred) + override def filterNot(pred: ((K, V)) => Boolean): MapView[K, V]^{this, pred} = new MapView.Filter(this, isFlipped = 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 @@ -86,55 +88,55 @@ object MapView extends MapViewFactory { override def knownSize: Int = 0 override def isEmpty: Boolean = true override def filterKeys(p: Any => Boolean): MapView[Any, Nothing] = this - override def mapValues[W](f: Nothing => W): MapView[Any, Nothing] = this + override def mapValues[W](f: Nothing => W): MapView[Any, W] = this // TODO: W is originally Nothing in return type, but breaks CC override def filter(pred: ((Any, Nothing)) => Boolean): MapView[Any, Nothing] = this override def filterNot(pred: ((Any, Nothing)) => Boolean): MapView[Any, Nothing] = this override def partition(p: ((Any, Nothing)) => Boolean): (MapView[Any, Nothing], MapView[Any, Nothing]) = (this, this) } @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 @@ -144,7 +146,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) => @@ -153,7 +155,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 } @@ -162,7 +164,7 @@ 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)]^{it} = View.from(it) override def from[K, V](it: SomeMapOps[K, V]): MapView[K, V] = it match { case mv: MapView[K, V] => mv diff --git a/library/src/scala/collection/Searching.scala b/library/src/scala/collection/Searching.scala index 7148f54606bf..cd5842f81057 100644 --- a/library/src/scala/collection/Searching.scala +++ b/library/src/scala/collection/Searching.scala @@ -14,6 +14,8 @@ package scala.collection import scala.language.`2.13` import scala.language.implicitConversions +import language.experimental.captureChecking + import scala.collection.generic.IsSeq object Searching { diff --git a/library/src/scala/collection/Seq.scala b/library/src/scala/collection/Seq.scala index 2f960a47f54f..46e488ba4662 100644 --- a/library/src/scala/collection/Seq.scala +++ b/library/src/scala/collection/Seq.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.immutable.Range import scala.util.hashing.MurmurHash3 import Searching.{Found, InsertionPoint, SearchResult} @@ -27,7 +29,8 @@ trait Seq[+A] with PartialFunction[Int, A] with SeqOps[A, Seq, Seq[A]] with IterableFactoryDefaults[A, Seq] - with Equals { + with Equals + with caps.Pure { override def iterableFactory: SeqFactory[Seq] = Seq @@ -76,9 +79,9 @@ object Seq extends SeqFactory.Delegate[Seq](immutable.Seq) * @define Coll `Seq` */ transparent trait SeqOps[+A, +CC[_], +C] extends Any - with IterableOps[A, CC, C] { self => + with IterableOps[A, CC, C] { self: SeqOps[A, CC, C]^ => - override def view: SeqView[A] = new SeqView.Id[A](this) + override def view: SeqView[A]^{this} = new SeqView.Id[A](this) /** Gets 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`. */ @@ -110,14 +113,14 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * @return a new $coll consisting of `value` followed * by all elements of this $coll. */ - def prepended[B >: A](elem: B): CC[B] = iterableFactory.from(new View.Prepended(elem, this)) + def prepended[B >: A](elem: B): CC[B]^{this} = iterableFactory.from(new View.Prepended(elem, this)) /** Alias for `prepended`. * * Note that :-ending operators are right associative (see example). * A mnemonic for `+:` vs. `:+` is: the COLon goes on the COLlection side. */ - @`inline` final def +: [B >: A](elem: B): CC[B] = prepended(elem) + @`inline` final def +: [B >: A](elem: B): CC[B]^{this} = prepended(elem) /** A copy of this $coll with an element appended. * @@ -140,14 +143,14 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * @return a new $coll consisting of * all elements of this $coll followed by `value`. */ - def appended[B >: A](elem: B): CC[B] = iterableFactory.from(new View.Appended(this, elem)) + def appended[B >: A](elem: B): CC[B]^{this} = iterableFactory.from(new View.Appended(this, elem)) /** Alias for `appended`. * * Note that :-ending operators are right associative (see example). * A mnemonic for `+:` vs. `:+` is: the COLon goes on the COLlection side. */ - @`inline` final def :+ [B >: A](elem: B): CC[B] = appended(elem) + @`inline` final def :+ [B >: A](elem: B): CC[B]^{this} = appended(elem) /** As with `:++`, returns a new collection containing the elements from the left operand followed by the * elements from the right operand. @@ -161,13 +164,13 @@ transparent 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]^{this, prefix} = 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 def ++: [B >: A](prefix: IterableOnce[B]^): CC[B]^{this, prefix} = 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 @@ -178,14 +181,14 @@ transparent 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]^{this, suffix} = super.concat(suffix) /** Alias for `appendedAll`. */ - @inline final def :++ [B >: A](suffix: IterableOnce[B]): CC[B] = appendedAll(suffix) + @inline def :++ [B >: A](suffix: IterableOnce[B]^): CC[B]^{this, suffix} = 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 override def concat[B >: A](suffix: IterableOnce[B]^): CC[B]^{this, suffix} = 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`. @@ -196,7 +199,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * followed by all elements of `that`. */ @deprecated("Use `concat` instead", "2.13.0") - @inline final def union[B >: A](that: Seq[B]): CC[B] = concat(that) + @inline final def union[B >: A](that: Seq[B]): CC[B]^{this} = concat(that) final override def size: Int = length @@ -204,7 +207,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * * @return a new $coll consisting of all the elements of this $coll without duplicates. */ - def distinct: C = distinctBy(identity) + def distinct: C^{this} = distinctBy(identity) /** Selects all the elements of this $coll ignoring the duplicates as determined by `==` after applying * the transforming function `f`. @@ -213,7 +216,7 @@ transparent 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^{this} = fromSpecific(new View.DistinctBy(this, f)) /** Returns a new $coll with the elements of this $coll in reverse order. * @@ -222,7 +225,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * * @return a new $coll with all elements of this $coll in reverse order. */ - def reverse: C = fromSpecific(reversed) + def reverse: C^{this} = fromSpecific(reversed) /** An iterator yielding the elements of this $coll in reverse order. * @@ -232,7 +235,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * * @return an iterator yielding the elements of this $coll in reverse order. */ - def reverseIterator: Iterator[A] = reversed.iterator + def reverseIterator: Iterator[A]^{this} = reversed.iterator /** Tests whether this $coll contains the given sequence at a given index. * @@ -244,7 +247,7 @@ transparent 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) @@ -259,7 +262,7 @@ transparent 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) @@ -291,7 +294,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * 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): CC[B] = iterableFactory.from(new View.PadTo(this, len, elem)) + def padTo[B >: A](len: Int, elem: B): CC[B]^{this} = iterableFactory.from(new View.PadTo(this, len, elem)) /** Computes the length of the longest segment that starts from the first element * and whose elements all satisfy some predicate. @@ -527,7 +530,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem) @deprecated("Use .reverseIterator.map(f).to(...) instead of .reverseMap(f)", "2.13.0") - def reverseMap[B](f: A => B): CC[B] = iterableFactory.from(new View.Map(View.fromIteratorProvider(() => reverseIterator), f)) + def reverseMap[B](f: A => B): CC[B]^{this, f} = iterableFactory.from(new View.Map(View.fromIteratorProvider(() => reverseIterator), f)) /** Iterates over distinct permutations of elements. * @@ -541,7 +544,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * // List(b, b, a) * }}} */ - def permutations: Iterator[C] = + def permutations: Iterator[C^{this}]^{this} = if (isEmpty) Iterator.single(coll) else new PermutationsItr @@ -582,7 +585,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * // List(b, a) * }}} */ - def combinations(n: Int): Iterator[C] = + def combinations(n: Int): Iterator[C^{this}]^{this} = if (n < 0 || n > size) Iterator.empty else new CombinationsItr(n) @@ -717,7 +720,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * @return a $coll consisting of the elements of this $coll * sorted according to the ordering `ord`. */ - def sorted[B >: A](implicit ord: Ordering[B]): C = { + def sorted[B >: A](implicit ord: Ordering[B]): C^{this} = { val len = this.length val b = newSpecificBuilder if (len == 1) b += head @@ -754,7 +757,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * List("Bobby", "Bob", "John", "Steve", "Tom") * }}} */ - def sortWith(lt: (A, A) => Boolean): C = sorted(Ordering.fromLessThan(lt)) + def sortWith(lt: (A, A) => Boolean): C^{this} = sorted(Ordering.fromLessThan(lt)) /** Sorts this $coll according to the Ordering which results from transforming * an implicitly given Ordering with a transformation function. @@ -781,7 +784,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped) * }}} */ - def sortBy[B](f: A => B)(implicit ord: Ordering[B]): C = sorted(ord on f) + def sortBy[B](f: A => B)(implicit ord: Ordering[B]): C^{this} = sorted(ord on f) /** Produces the range of all indices of this sequence. * $willForceEvaluation @@ -809,7 +812,7 @@ transparent 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`. * @@ -824,7 +827,7 @@ transparent 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. * @@ -840,7 +843,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * this.lengthIs > len // this.lengthCompare(len) > 0 * }}} */ - @inline final def lengthIs: IterableOps.SizeCompareOps = new IterableOps.SizeCompareOps(this) + @inline final def lengthIs: IterableOps.SizeCompareOps^{this} = new IterableOps.SizeCompareOps(caps.unsafe.unsafeAssumePure(this) /* see comment in SizeCompareOps*/) override def isEmpty: Boolean = lengthCompare(0) == 0 @@ -851,7 +854,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * @tparam B the type of the elements of collection `that`. * @return `true` if both collections contain equal elements in the same order, `false` otherwise. */ - def sameElements[B >: A](that: IterableOnce[B]): Boolean = { + def sameElements[B >: A](that: IterableOnce[B]^): Boolean = { val thisKnownSize = knownSize if (thisKnownSize != -1) { val thatKnownSize = that.knownSize @@ -891,7 +894,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * ''n'' times in `that`, then the first ''n'' occurrences of `x` will not form * part of the result, but any following occurrences will. */ - def diff[B >: A](that: Seq[B]): C = { + def diff[B >: A](that: Seq[B]): C^{this} = { val occ = occCounts(that) fromSpecific(iterator.filter { x => var include = false @@ -916,7 +919,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * ''n'' times in `that`, then the first ''n'' occurrences of `x` will be retained * in the result, but any following occurrences will be omitted. */ - def intersect[B >: A](that: Seq[B]): C = { + def intersect[B >: A](that: Seq[B]): C^{this} = { val occ = occCounts(that) fromSpecific(iterator.filter { x => var include = true @@ -946,7 +949,7 @@ transparent 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]^{this, other} = iterableFactory.from(new View.Patched(this, from, other, replaced)) /** A copy of this $coll with one single replaced element. @@ -958,7 +961,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any * lazy collection this exception may be thrown at a later time or not at * all (if the end of the collection is never evaluated). */ - def updated[B >: A](index: Int, elem: B): CC[B] = { + def updated[B >: A](index: Int, elem: B): CC[B]^{this} = { if(index < 0) throw new IndexOutOfBoundsException(index.toString) val k = knownSize if(k >= 0 && index >= k) throw new IndexOutOfBoundsException(index.toString) @@ -1013,14 +1016,14 @@ transparent 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) + private[this] def linearSearch[B >: A](c: View[A]^, elem: B, offset: Int) (implicit ord: Ordering[B]): SearchResult = { var idx = offset val it = c.iterator @@ -1170,7 +1173,7 @@ object SeqOps { * @param wlen Just in case we're only IndexedSeq and not IndexedSeqOptimized * @return KMP jump table for target sequence */ - private def kmpJumpTable[B](Wopt: IndexedSeqView[B], wlen: Int) = { + private def kmpJumpTable[B](Wopt: IndexedSeqView[B]^, wlen: Int) = { val arr = new Array[Int](wlen) var pos = 2 var cnd = 0 diff --git a/library/src/scala/collection/SeqMap.scala b/library/src/scala/collection/SeqMap.scala index 17d187975af2..076ae34c9752 100644 --- a/library/src/scala/collection/SeqMap.scala +++ b/library/src/scala/collection/SeqMap.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn /** @@ -30,7 +32,8 @@ import scala.annotation.nowarn trait SeqMap[K, +V] extends Map[K, V] with MapOps[K, V, SeqMap, SeqMap[K, V]] - with MapFactoryDefaults[K, V, SeqMap, Iterable] { + with MapFactoryDefaults[K, V, SeqMap, Iterable] + with caps.Pure { @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") override protected[this] def stringPrefix: String = "SeqMap" diff --git a/library/src/scala/collection/SeqView.scala b/library/src/scala/collection/SeqView.scala index 3f6a4c5c3ea4..960de6f1d752 100644 --- a/library/src/scala/collection/SeqView.scala +++ b/library/src/scala/collection/SeqView.scala @@ -14,28 +14,30 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn import scala.collection.generic.CommonErrors 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, suffix} = new SeqView.Concat(this, suffix) + def appendedAll[B >: A](suffix: SeqView.SomeSeqOps[B]^): SeqView[B]^{this, suffix} = new SeqView.Concat(this, suffix) + def prependedAll[B >: A](prefix: SeqView.SomeSeqOps[B]^): SeqView[B]^{this, prefix} = 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" @@ -48,34 +50,34 @@ object SeqView { /** 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) @@ -84,16 +86,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 { @@ -106,7 +108,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] @@ -114,15 +116,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] @@ -130,15 +132,17 @@ object SeqView { } @SerialVersionUID(3L) - class Sorted[A, B >: A] private (private[this] var underlying: SomeSeqOps[A], + class Sorted[A, B >: A] private (underlying_ : SomeSeqOps[A]^, private[this] val len: Int, ord: Ordering[B]) extends SeqView[A] { - outer => + outer: Sorted[A, B]^ => + + private var underlying = underlying_ // 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] { @@ -150,10 +154,10 @@ object SeqView { 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]^{this} = outer + override protected def reversed: Iterable[A]^{outer} = outer - 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 == Sorted.this.ord) outer else if (ord1.isReverseOf(Sorted.this.ord)) this else new Sorted(elems, len, ord1) @@ -187,14 +191,14 @@ object SeqView { res } - private[this] def elems: SomeSeqOps[A] = { - val orig = underlying + private[this] def elems: SomeSeqOps[A]^{this} = { + val orig: SomeSeqOps[A]^{this} = 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) @@ -203,7 +207,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/library/src/scala/collection/Set.scala b/library/src/scala/collection/Set.scala index 78bf6351c84c..c5f879dc1644 100644 --- a/library/src/scala/collection/Set.scala +++ b/library/src/scala/collection/Set.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.util.hashing.MurmurHash3 import java.lang.String @@ -25,7 +27,8 @@ trait Set[A] extends Iterable[A] with SetOps[A, Set, Set[A]] with Equals - with IterableFactoryDefaults[A, Set] { + with IterableFactoryDefaults[A, Set] + with caps.Pure { def canEqual(that: Any) = true @@ -88,7 +91,8 @@ trait Set[A] */ transparent trait SetOps[A, +CC[_], +C <: SetOps[A, CC, C]] extends IterableOps[A, CC, C] - with (A => Boolean) { + with (A => Boolean) + with caps.Pure { def contains(elem: A): Boolean @@ -200,7 +204,7 @@ transparent trait SetOps[A, +CC[_], +C <: SetOps[A, CC, C]] @`inline` final def &~ (that: Set[A]): C = this diff that @deprecated("Consider requiring an immutable Set", "2.13.0") - def -- (that: IterableOnce[A]): C = { + def -- (that: IterableOnce[A]^): C = { val toRemove = that.iterator.to(immutable.Set) fromSpecific(view.filterNot(toRemove)) } @@ -222,7 +226,7 @@ transparent trait SetOps[A, +CC[_], +C <: SetOps[A, CC, C]] * @param that the collection containing the elements to add. * @return a new $coll with the given elements added, omitting duplicates. */ - def concat(that: collection.IterableOnce[A]): C = this match { + def concat(that: collection.IterableOnce[A]^): C = this match { case optimizedSet @ (_ : scala.collection.immutable.Set.Set1[A] | _: scala.collection.immutable.Set.Set2[A] | _: scala.collection.immutable.Set.Set3[A] | _: scala.collection.immutable.Set.Set4[A]) => // StrictOptimizedSetOps optimization of concat (these Sets cannot extend StrictOptimizedSetOps because of binary-incompatible return type; cf. PR #10036) var result = optimizedSet.asInstanceOf[scala.collection.immutable.SetOps[A, scala.collection.immutable.Set, scala.collection.immutable.Set[A]]] @@ -242,7 +246,7 @@ transparent trait SetOps[A, +CC[_], +C <: SetOps[A, CC, C]] def + (elem1: A, elem2: A, elems: A*): C = fromSpecific(new View.Concat(new View.Appended(new View.Appended(this, elem1), elem2), elems)) /** Alias for `concat` */ - @`inline` final def ++ (that: collection.IterableOnce[A]): C = concat(that) + @`inline` final def ++ (that: collection.IterableOnce[A]^): C = concat(that) /** Computes the union between of set and another set. * diff --git a/library/src/scala/collection/SortedMap.scala b/library/src/scala/collection/SortedMap.scala index d4f1aae2b62e..3a3b23be2409 100644 --- a/library/src/scala/collection/SortedMap.scala +++ b/library/src/scala/collection/SortedMap.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{implicitNotFound, nowarn} /** A Map whose keys are sorted according to a [[scala.math.Ordering]]*/ @@ -48,9 +50,10 @@ trait SortedMap[K, +V] } } -transparent trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], +C <: SortedMapOps[K, V, CC, C]] +transparent trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _] with caps.Pure, +C <: SortedMapOps[K, V, CC, C]] extends MapOps[K, V, Map, C] - with SortedOps[K, C] { + with SortedOps[K, C] + with caps.Pure { /** The companion object of this sorted map, providing various factory methods. * @@ -63,7 +66,7 @@ transparent trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X /** Similar to `mapFromIterable`, but returns a SortedMap collection type. * Note that the return type is now `CC[K2, V2]`. */ - @`inline` protected final def sortedMapFromIterable[K2, V2](it: Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] = sortedMapFactory.from(it) + @`inline` protected final def sortedMapFromIterable[K2, V2](it: Iterable[(K2, V2)]^)(implicit ordering: Ordering[K2]): CC[K2, V2] = sortedMapFactory.from(it) def unsorted: Map[K, V] @@ -163,7 +166,7 @@ transparent trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X * @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)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = + def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^)(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = sortedMapFactory.from(new View.FlatMap(this, f)) /** Builds a new sorted map by applying a partial function to all elements of this $coll @@ -174,16 +177,16 @@ transparent trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X * `pf` to each element on which it is defined and collecting the results. * The order of the elements is preserved. */ - def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = + 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) })(using 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))(using ordering) @@ -207,10 +210,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/library/src/scala/collection/SortedOps.scala b/library/src/scala/collection/SortedOps.scala index 4fefcc4038d0..b995ef9e1911 100644 --- a/library/src/scala/collection/SortedOps.scala +++ b/library/src/scala/collection/SortedOps.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking /** Base trait for sorted collections */ transparent trait SortedOps[A, +C] { diff --git a/library/src/scala/collection/SortedSet.scala b/library/src/scala/collection/SortedSet.scala index 9290087cf06b..ed3cfaee73da 100644 --- a/library/src/scala/collection/SortedSet.scala +++ b/library/src/scala/collection/SortedSet.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{implicitNotFound, nowarn} import scala.annotation.unchecked.uncheckedVariance @@ -130,7 +132,7 @@ transparent trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[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])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = + def flatMap[B](f: A => IterableOnce[B]^)(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = sortedIterableFactory.from(new View.FlatMap(this, f)) /** Returns a $coll formed from this $coll and another iterable collection @@ -142,7 +144,7 @@ transparent trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, * @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])(implicit @implicitNotFound(SortedSetOps.zipOrdMsg) ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = // sound bcs of VarianceNote + def zip[B](that: IterableOnce[B]^)(implicit @implicitNotFound(SortedSetOps.zipOrdMsg) ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = // sound bcs of VarianceNote sortedIterableFactory.from(that match { case that: Iterable[B] => new View.Zip(this, that) case _ => iterator.zip(that) @@ -157,7 +159,7 @@ transparent trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[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: scala.PartialFunction[A, B])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = + def collect[B](pf: scala.PartialFunction[A, B]^)(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = sortedIterableFactory.from(new View.Collect(this, pf)) } @@ -177,10 +179,10 @@ object SortedSetOps { def map[B : Ordering](f: A => B): CC[B] = self.sortedIterableFactory.from(new View.Map(filtered, f)) - def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = + 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/library/src/scala/collection/Stepper.scala b/library/src/scala/collection/Stepper.scala index 8755142d7209..7c4b5821aef9 100644 --- a/library/src/scala/collection/Stepper.scala +++ b/library/src/scala/collection/Stepper.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.function.{Consumer, DoubleConsumer, IntConsumer, LongConsumer} import java.util.{PrimitiveIterator, Spliterator, Iterator => JIterator} import java.{lang => jl} @@ -52,7 +54,7 @@ trait Stepper[@specialized(Double, Int, Long) +A] { * * See method `trySplit` in [[java.util.Spliterator]]. */ - def trySplit(): Stepper[A] + def trySplit(): Stepper[A]^{this} /** Returns an estimate of the number of elements of this Stepper, or [[Long.MaxValue]]. See * method `estimateSize` in [[java.util.Spliterator]]. @@ -70,7 +72,7 @@ trait Stepper[@specialized(Double, Int, Long) +A] { * a [[java.util.Spliterator.OfInt]] (which is a `Spliterator[Integer]`) in the subclass [[IntStepper]] * (which is a `Stepper[Int]`). */ - def spliterator[B >: A]: Spliterator[_] + def spliterator[B >: A]: Spliterator[_]^{this} /** Returns a Java [[java.util.Iterator]] corresponding to this Stepper. * @@ -78,12 +80,12 @@ trait Stepper[@specialized(Double, Int, Long) +A] { * a [[java.util.PrimitiveIterator.OfInt]] (which is a `Iterator[Integer]`) in the subclass * [[IntStepper]] (which is a `Stepper[Int]`). */ - def javaIterator[B >: A]: JIterator[_] + def javaIterator[B >: A]: JIterator[_]^{this} /** Returns an [[Iterator]] corresponding to this Stepper. Note that Iterators corresponding to * primitive Steppers box the elements. */ - def iterator: Iterator[A] = new AbstractIterator[A] { + def iterator: Iterator[A]^{this} = new AbstractIterator[A] { def hasNext: Boolean = hasStep def next(): A = nextStep() } @@ -104,78 +106,78 @@ object Stepper { * of the data is boxed. In other cases native implementations of the primitive stepper types should be provided * (see for example IntArrayStepper and WidenedByteArrayStepper). */ - private[collection] class UnboxingDoubleStepper(st: AnyStepper[Double]) extends DoubleStepper { + private[collection] class UnboxingDoubleStepper(st: AnyStepper[Double]^) extends DoubleStepper { def hasStep: Boolean = st.hasStep def nextStep(): Double = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): DoubleStepper = { + def trySplit(): DoubleStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingDoubleStepper(s) } } - private[collection] class UnboxingIntStepper(st: AnyStepper[Int]) extends IntStepper { + private[collection] class UnboxingIntStepper(st: AnyStepper[Int]^) extends IntStepper { def hasStep: Boolean = st.hasStep def nextStep(): Int = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): IntStepper = { + def trySplit(): IntStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingIntStepper(s) } } - private[collection] class UnboxingLongStepper(st: AnyStepper[Long]) extends LongStepper { + private[collection] class UnboxingLongStepper(st: AnyStepper[Long]^) extends LongStepper { def hasStep: Boolean = st.hasStep def nextStep(): Long = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): LongStepper = { + def trySplit(): LongStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingLongStepper(s) } } - private[collection] class UnboxingByteStepper(st: AnyStepper[Byte]) extends IntStepper { + private[collection] class UnboxingByteStepper(st: AnyStepper[Byte]^) extends IntStepper { def hasStep: Boolean = st.hasStep def nextStep(): Int = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): IntStepper = { + def trySplit(): IntStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingByteStepper(s) } } - private[collection] class UnboxingCharStepper(st: AnyStepper[Char]) extends IntStepper { + private[collection] class UnboxingCharStepper(st: AnyStepper[Char]^) extends IntStepper { def hasStep: Boolean = st.hasStep def nextStep(): Int = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): IntStepper = { + def trySplit(): IntStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingCharStepper(s) } } - private[collection] class UnboxingShortStepper(st: AnyStepper[Short]) extends IntStepper { + private[collection] class UnboxingShortStepper(st: AnyStepper[Short]^) extends IntStepper { def hasStep: Boolean = st.hasStep def nextStep(): Int = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): IntStepper = { + def trySplit(): IntStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingShortStepper(s) } } - private[collection] class UnboxingFloatStepper(st: AnyStepper[Float]) extends DoubleStepper { + private[collection] class UnboxingFloatStepper(st: AnyStepper[Float]^) extends DoubleStepper { def hasStep: Boolean = st.hasStep def nextStep(): Double = st.nextStep() def estimateSize: Long = st.estimateSize def characteristics: Int = st.characteristics - def trySplit(): DoubleStepper = { + def trySplit(): DoubleStepper^{this} = { val s = st.trySplit() if (s == null) null else new UnboxingFloatStepper(s) } @@ -184,21 +186,21 @@ object Stepper { /** A Stepper for arbitrary element types. See [[Stepper]]. */ trait AnyStepper[+A] extends Stepper[A] { - def trySplit(): AnyStepper[A] + def trySplit(): AnyStepper[A]^{this} - 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 javaIterator[B >: A]: JIterator[B]^{this} = new JIterator[B] { def hasNext: Boolean = hasStep def next(): B = nextStep() } } 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 } @@ -254,9 +256,9 @@ object AnyStepper { /** A Stepper for Ints. See [[Stepper]]. */ trait IntStepper extends Stepper[Int] { - def trySplit(): IntStepper + def trySplit(): IntStepper^{this} - 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 @@ -264,7 +266,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 @@ -273,7 +275,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 } @@ -292,9 +294,9 @@ object IntStepper { /** A Stepper for Doubles. See [[Stepper]]. */ trait DoubleStepper extends Stepper[Double] { - def trySplit(): DoubleStepper + def trySplit(): DoubleStepper^{this} - 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 hasNext: Boolean = hasStep @@ -303,7 +305,7 @@ trait DoubleStepper extends Stepper[Double] { } 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 @@ -312,7 +314,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 } @@ -331,9 +333,9 @@ object DoubleStepper { /** A Stepper for Longs. See [[Stepper]]. */ trait LongStepper extends Stepper[Long] { - def trySplit(): 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 hasNext: Boolean = hasStep @@ -342,7 +344,7 @@ trait LongStepper extends Stepper[Long] { } 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 @@ -351,7 +353,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/library/src/scala/collection/StepperShape.scala b/library/src/scala/collection/StepperShape.scala index ec193cc27fc2..1b25d8758da0 100644 --- a/library/src/scala/collection/StepperShape.scala +++ b/library/src/scala/collection/StepperShape.scala @@ -15,22 +15,24 @@ package scala.collection import java.{lang => jl} import scala.language.`2.13` +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[_]] { self => /** Return the Int constant (as defined in the `StepperShape` companion object) for this `StepperShape`. */ def shape: StepperShape.Shape /** Create an unboxing primitive sequential Stepper from a boxed `AnyStepper`. * This is an identity operation for reference shapes. */ - def seqUnbox(st: AnyStepper[T]): S + def seqUnbox(st: AnyStepper[T]^): S^{st} /** Create an unboxing primitive parallel (i.e. `with EfficientSplit`) Stepper from a boxed `AnyStepper`. * This is an identity operation for reference shapes. */ - def parUnbox(st: AnyStepper[T] with EfficientSplit): S with EfficientSplit + def parUnbox(st: (AnyStepper[T] with EfficientSplit)^): (S with EfficientSplit)^{st} } object StepperShape extends StepperShapeLowPriority1 { @@ -52,50 +54,50 @@ object StepperShape extends StepperShapeLowPriority1 { implicit val intStepperShape: StepperShape[Int, IntStepper] = new StepperShape[Int, IntStepper] { def shape = IntShape - def seqUnbox(st: AnyStepper[Int]): IntStepper = new Stepper.UnboxingIntStepper(st) - def parUnbox(st: AnyStepper[Int] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingIntStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Int]^): IntStepper^{st} = new Stepper.UnboxingIntStepper(st) + def parUnbox(st: (AnyStepper[Int] with EfficientSplit)^): (IntStepper with EfficientSplit)^{st} = new Stepper.UnboxingIntStepper(st) with EfficientSplit } implicit val jIntegerStepperShape: StepperShape[jl.Integer, IntStepper] = intStepperShape.asInstanceOf[StepperShape[jl.Integer, IntStepper]] implicit val longStepperShape: StepperShape[Long, LongStepper] = new StepperShape[Long, LongStepper] { def shape = LongShape - def seqUnbox(st: AnyStepper[Long]): LongStepper = new Stepper.UnboxingLongStepper(st) - def parUnbox(st: AnyStepper[Long] with EfficientSplit): LongStepper with EfficientSplit = new Stepper.UnboxingLongStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Long]^): LongStepper^{st} = new Stepper.UnboxingLongStepper(st) + def parUnbox(st: (AnyStepper[Long] with EfficientSplit)^): (LongStepper with EfficientSplit)^{st} = new Stepper.UnboxingLongStepper(st) with EfficientSplit } implicit val jLongStepperShape: StepperShape[jl.Long, LongStepper] = longStepperShape.asInstanceOf[StepperShape[jl.Long, LongStepper]] implicit val doubleStepperShape: StepperShape[Double, DoubleStepper] = new StepperShape[Double, DoubleStepper] { def shape = DoubleShape - def seqUnbox(st: AnyStepper[Double]): DoubleStepper = new Stepper.UnboxingDoubleStepper(st) - def parUnbox(st: AnyStepper[Double] with EfficientSplit): DoubleStepper with EfficientSplit = new Stepper.UnboxingDoubleStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Double]^): DoubleStepper^{st} = new Stepper.UnboxingDoubleStepper(st) + def parUnbox(st: (AnyStepper[Double] with EfficientSplit)^): (DoubleStepper with EfficientSplit)^{st} = new Stepper.UnboxingDoubleStepper(st) with EfficientSplit } implicit val jDoubleStepperShape: StepperShape[jl.Double, DoubleStepper] = doubleStepperShape.asInstanceOf[StepperShape[jl.Double, DoubleStepper]] implicit val byteStepperShape: StepperShape[Byte, IntStepper] = new StepperShape[Byte, IntStepper] { def shape = ByteShape - def seqUnbox(st: AnyStepper[Byte]): IntStepper = new Stepper.UnboxingByteStepper(st) - def parUnbox(st: AnyStepper[Byte] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingByteStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Byte]^): IntStepper^{st} = new Stepper.UnboxingByteStepper(st) + def parUnbox(st: (AnyStepper[Byte] with EfficientSplit)^): (IntStepper with EfficientSplit)^{st} = new Stepper.UnboxingByteStepper(st) with EfficientSplit } implicit val jByteStepperShape: StepperShape[jl.Byte, IntStepper] = byteStepperShape.asInstanceOf[StepperShape[jl.Byte, IntStepper]] implicit val shortStepperShape: StepperShape[Short, IntStepper] = new StepperShape[Short, IntStepper] { def shape = ShortShape - def seqUnbox(st: AnyStepper[Short]): IntStepper = new Stepper.UnboxingShortStepper(st) - def parUnbox(st: AnyStepper[Short] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingShortStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Short]^): IntStepper^{st} = new Stepper.UnboxingShortStepper(st) + def parUnbox(st: (AnyStepper[Short] with EfficientSplit)^): (IntStepper with EfficientSplit)^{st} = new Stepper.UnboxingShortStepper(st) with EfficientSplit } implicit val jShortStepperShape: StepperShape[jl.Short, IntStepper] = shortStepperShape.asInstanceOf[StepperShape[jl.Short, IntStepper]] implicit val charStepperShape: StepperShape[Char, IntStepper] = new StepperShape[Char, IntStepper] { def shape = CharShape - def seqUnbox(st: AnyStepper[Char]): IntStepper = new Stepper.UnboxingCharStepper(st) - def parUnbox(st: AnyStepper[Char] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingCharStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Char]^): IntStepper^{st} = new Stepper.UnboxingCharStepper(st) + def parUnbox(st: (AnyStepper[Char] with EfficientSplit)^): (IntStepper with EfficientSplit)^{st} = new Stepper.UnboxingCharStepper(st) with EfficientSplit } implicit val jCharacterStepperShape: StepperShape[jl.Character, IntStepper] = charStepperShape.asInstanceOf[StepperShape[jl.Character, IntStepper]] implicit val floatStepperShape: StepperShape[Float, DoubleStepper] = new StepperShape[Float, DoubleStepper] { def shape = FloatShape - def seqUnbox(st: AnyStepper[Float]): DoubleStepper = new Stepper.UnboxingFloatStepper(st) - def parUnbox(st: AnyStepper[Float] with EfficientSplit): DoubleStepper with EfficientSplit = new Stepper.UnboxingFloatStepper(st) with EfficientSplit + def seqUnbox(st: AnyStepper[Float]^): DoubleStepper^{st} = new Stepper.UnboxingFloatStepper(st) + def parUnbox(st: (AnyStepper[Float] with EfficientSplit)^): (DoubleStepper with EfficientSplit)^{st} = new Stepper.UnboxingFloatStepper(st) with EfficientSplit } implicit val jFloatStepperShape: StepperShape[jl.Float, DoubleStepper] = floatStepperShape.asInstanceOf[StepperShape[jl.Float, DoubleStepper]] } @@ -109,7 +111,7 @@ trait StepperShapeLowPriority2 { protected val anyStepperShapePrototype: StepperShape[AnyRef, Stepper[AnyRef]] = new StepperShape[AnyRef, Stepper[AnyRef]] { def shape = StepperShape.ReferenceShape - def seqUnbox(st: AnyStepper[AnyRef]): Stepper[AnyRef] = st - def parUnbox(st: AnyStepper[AnyRef] with EfficientSplit): Stepper[AnyRef] with EfficientSplit = st + def seqUnbox(st: AnyStepper[AnyRef]^): Stepper[AnyRef]^{st} = st + def parUnbox(st: (AnyStepper[AnyRef] with EfficientSplit)^): (Stepper[AnyRef] with EfficientSplit)^{st} = st } -} \ No newline at end of file +} diff --git a/library/src/scala/collection/StrictOptimizedIterableOps.scala b/library/src/scala/collection/StrictOptimizedIterableOps.scala index 81c8a79aedf4..b89acb715cf7 100644 --- a/library/src/scala/collection/StrictOptimizedIterableOps.scala +++ b/library/src/scala/collection/StrictOptimizedIterableOps.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.nowarn import scala.annotation.unchecked.uncheckedVariance import scala.runtime.Statics @@ -56,7 +58,7 @@ transparent 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 => @@ -67,7 +69,7 @@ transparent 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] @@ -103,7 +105,7 @@ transparent 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) /** @@ -113,7 +115,7 @@ transparent 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()) @@ -128,13 +130,13 @@ transparent 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) /** @@ -144,7 +146,7 @@ transparent 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) { @@ -155,7 +157,7 @@ transparent 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) /** @@ -173,7 +175,7 @@ transparent 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)]) /** @@ -183,7 +185,7 @@ transparent 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) { @@ -246,7 +248,7 @@ transparent trait StrictOptimizedIterableOps[+A, +CC[_], +C] } // Optimization avoids creation of second collection - override def tapEach[U](f: A => U): C = { + override def tapEach[U](f: A => U): C^{this} = { foreach(f) coll } diff --git a/library/src/scala/collection/StrictOptimizedMapOps.scala b/library/src/scala/collection/StrictOptimizedMapOps.scala index cc594f268c07..b5eaa0d1638d 100644 --- a/library/src/scala/collection/StrictOptimizedMapOps.scala +++ b/library/src/scala/collection/StrictOptimizedMapOps.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking /** * Trait that overrides map operations to take advantage of strict builders. @@ -29,13 +30,13 @@ transparent trait StrictOptimizedMapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyCo 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] = + override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]^): CC[K2, V2] = strictOptimizedCollect(mapFactory.newBuilder, pf) @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") diff --git a/library/src/scala/collection/StrictOptimizedSeqOps.scala b/library/src/scala/collection/StrictOptimizedSeqOps.scala index cf59f7b05b9e..297473fee3ee 100644 --- a/library/src/scala/collection/StrictOptimizedSeqOps.scala +++ b/library/src/scala/collection/StrictOptimizedSeqOps.scala @@ -13,17 +13,16 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking /** * Trait that overrides operations on sequences in order * to take advantage of strict builders. */ -transparent trait StrictOptimizedSeqOps [+A, +CC[_], +C] - extends Any - with SeqOps[A, CC, C] - with StrictOptimizedIterableOps[A, CC, C] { +transparent trait StrictOptimizedSeqOps [+A, +CC[_] <: caps.Pure, +C] + extends Any with SeqOps[A, CC, C] with StrictOptimizedIterableOps[A, CC, C] with caps.Pure { - 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 @@ -50,10 +49,10 @@ transparent 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 diff --git a/library/src/scala/collection/StrictOptimizedSetOps.scala b/library/src/scala/collection/StrictOptimizedSetOps.scala index cef517c39fd6..5e5349b6cd78 100644 --- a/library/src/scala/collection/StrictOptimizedSetOps.scala +++ b/library/src/scala/collection/StrictOptimizedSetOps.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking /** * Trait that overrides set operations to take advantage of strict builders. @@ -25,7 +26,7 @@ transparent trait StrictOptimizedSetOps[A, +CC[_], +C <: SetOps[A, CC, C]] extends SetOps[A, CC, C] with StrictOptimizedIterableOps[A, CC, C] { - override def concat(that: IterableOnce[A]): C = + override def concat(that: IterableOnce[A]^): C = strictOptimizedConcat(that, newSpecificBuilder) } diff --git a/library/src/scala/collection/StrictOptimizedSortedMapOps.scala b/library/src/scala/collection/StrictOptimizedSortedMapOps.scala index c71ad8d1e447..e9328dfb01e4 100644 --- a/library/src/scala/collection/StrictOptimizedSortedMapOps.scala +++ b/library/src/scala/collection/StrictOptimizedSortedMapOps.scala @@ -13,6 +13,8 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.implicitNotFound /** @@ -30,13 +32,13 @@ transparent trait StrictOptimizedSortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with override def map[K2, V2](f: ((K, V)) => (K2, V2))(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = strictOptimizedMap(sortedMapFactory.newBuilder, f) - override def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = + 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(using ordering)) - override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = + override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]^)(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = strictOptimizedCollect(sortedMapFactory.newBuilder, pf) @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") diff --git a/library/src/scala/collection/StrictOptimizedSortedSetOps.scala b/library/src/scala/collection/StrictOptimizedSortedSetOps.scala index aef85be58bb3..d9c437573ca2 100644 --- a/library/src/scala/collection/StrictOptimizedSortedSetOps.scala +++ b/library/src/scala/collection/StrictOptimizedSortedSetOps.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.implicitNotFound import scala.annotation.unchecked.uncheckedVariance @@ -31,13 +33,13 @@ transparent trait StrictOptimizedSortedSetOps[A, +CC[X] <: SortedSet[X], +C <: S override def map[B](f: A => B)(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = strictOptimizedMap(sortedIterableFactory.newBuilder, f) - override def flatMap[B](f: A => IterableOnce[B])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = + override def flatMap[B](f: A => IterableOnce[B]^)(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = strictOptimizedFlatMap(sortedIterableFactory.newBuilder, f) - override def zip[B](that: IterableOnce[B])(implicit @implicitNotFound(SortedSetOps.zipOrdMsg) ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = + override def zip[B](that: IterableOnce[B]^)(implicit @implicitNotFound(SortedSetOps.zipOrdMsg) ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = strictOptimizedZip(that, sortedIterableFactory.newBuilder[(A, B)]) - override def collect[B](pf: PartialFunction[A, B])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = + override def collect[B](pf: PartialFunction[A, B]^)(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = strictOptimizedCollect(sortedIterableFactory.newBuilder, pf) } diff --git a/library/src/scala/collection/StringOps.scala b/library/src/scala/collection/StringOps.scala index ab5ec5c1ff49..17800cb1d98b 100644 --- a/library/src/scala/collection/StringOps.scala +++ b/library/src/scala/collection/StringOps.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import java.lang.{StringBuilder => JStringBuilder} import scala.collection.Stepper.EfficientSplit @@ -122,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 @@ -154,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^{this, q} = new WithFilter(a => p(a) && q(a), s) } /** Avoid an allocation in [[collect]]. */ @@ -176,7 +178,7 @@ object StringOps { * are handled correctly. Failing to do so may result in * an invalid Unicode string. */ -final class StringOps(private val s: String) extends AnyVal { +final class StringOps(private val s: String) extends AnyVal { self => import StringOps._ @inline def view: StringView = new StringView(s) @@ -237,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 @@ -273,7 +275,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a new String resulting from applying the given partial function * `pf` to each char on which it is defined and collecting the results. */ - def collect(pf: PartialFunction[Char, Char]): String = { + def collect(pf: PartialFunction[Char, Char]^): String = { val fallback: Any => Any = StringOps.fallback var i = 0 val b = new StringBuilder @@ -293,7 +295,7 @@ final class StringOps(private val s: String) extends AnyVal { * @return a new collection resulting from applying the given partial function * `pf` to each char on which it is defined and collecting the results. */ - def collect[B](pf: PartialFunction[Char, B]): immutable.IndexedSeq[B] = { + def collect[B](pf: PartialFunction[Char, B]^): immutable.IndexedSeq[B] = { val fallback: Any => Any = StringOps.fallback var i = 0 val b = immutable.IndexedSeq.newBuilder[B] @@ -312,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)) @@ -328,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) @@ -346,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) @@ -421,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)) @@ -431,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 @@ -459,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 */ @@ -485,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)) @@ -514,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. @@ -1196,7 +1198,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. * @throws UnsupportedOperationException if the string is empty. @@ -1249,7 +1251,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. */ @@ -1467,7 +1469,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) /* ************************************************************************************************************ @@ -1515,7 +1517,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/library/src/scala/collection/StringParsers.scala b/library/src/scala/collection/StringParsers.scala index cfaa4f86985f..6c4807bf1929 100644 --- a/library/src/scala/collection/StringParsers.scala +++ b/library/src/scala/collection/StringParsers.scala @@ -14,6 +14,8 @@ package scala package collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.tailrec /** A module containing the implementations of parsers from strings to numeric types, and boolean diff --git a/library/src/scala/collection/View.scala b/library/src/scala/collection/View.scala index 690ba49aafe8..6b862aece4ea 100644 --- a/library/src/scala/collection/View.scala +++ b/library/src/scala/collection/View.scala @@ -13,9 +13,12 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{nowarn, tailrec} import scala.collection.mutable.{ArrayBuffer, Builder} import scala.collection.immutable.LazyList +import caps.unsafe.unsafeAssumePure /** 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`), @@ -25,7 +28,7 @@ import scala.collection.immutable.LazyList */ trait View[+A] extends Iterable[A] with IterableOps[A, View, View[A]] with IterableFactoryDefaults[A, View] with Serializable { - override def view: View[A] = this + override def view: View[A]^{this} = this override def iterableFactory: IterableFactory[View] = View @@ -56,7 +59,7 @@ object View extends IterableFactory[View] { * * @tparam A View element type */ - def fromIteratorProvider[A](it: () => Iterator[A]): View[A] = new AbstractView[A] { + def fromIteratorProvider[A](it: () => Iterator[A]^): View[A]^{it} = new AbstractView[A] { def iterator = it() } @@ -68,10 +71,10 @@ object View extends IterableFactory[View] { * * @tparam E View element type */ - def from[E](it: IterableOnce[E]): View[E] = it match { - case it: View[E] => it - case it: Iterable[E] => View.fromIteratorProvider(() => it.iterator) - case _ => LazyList.from(it).view + def from[E](it: IterableOnce[E]^): View[E]^{it} = it match { + case it: (View[E]^{it}) => it + case it: (Iterable[E]^{it}) => View.fromIteratorProvider(() => it.iterator) + case _ => LazyList.from(it).view } def empty[A]: View[A] = Empty @@ -115,7 +118,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 } @@ -123,7 +126,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 } @@ -133,7 +136,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 */ @@ -141,30 +144,34 @@ 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] { + class Filter[A](val underlying: SomeIterableOps[A]^, val p: A => Boolean, val isFlipped: Boolean) extends AbstractView[A] { def iterator = 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 filter : Filter[A] if filter.isFlipped == isFlipped => { + val f: Filter[A]^{underlying} = filter.unsafeAssumePure // TODO remove when pattern matching works + val f2: Filter[A]^{f, p} = new Filter(f.underlying, a => f.p(a) && p(a), isFlipped) + f2 + } case _ => new Filter(underlying, p, isFlipped) } } /** 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] { + class LeftPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A]^, f: A => Either[A1, A2]) extends AbstractView[A1] { def iterator: AbstractIterator[A1] = new AbstractIterator[A1] { private[this] val self = underlying.iterator private[this] var hd: A1 = _ @@ -189,7 +196,7 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - class RightPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A], f: A => Either[A1, A2]) extends AbstractView[A2] { + class RightPartitionMapped[A, A1, A2](underlying: SomeIterableOps[A]^, f: A => Either[A1, A2]) extends AbstractView[A2] { def iterator: AbstractIterator[A2] = new AbstractIterator[A2] { private[this] val self = underlying.iterator private[this] var hd: A2 = _ @@ -215,7 +222,7 @@ 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] { + class Drop[A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { def iterator = underlying.iterator.drop(n) protected val normN = n max 0 override def knownSize = { @@ -227,7 +234,7 @@ 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] { + class DropRight[A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { def iterator = dropRightIterator(underlying.iterator, n) protected val normN = n max 0 override def knownSize = { @@ -240,7 +247,7 @@ object View extends IterableFactory[View] { } @SerialVersionUID(3L) - class DropWhile[A](underlying: SomeIterableOps[A], p: A => Boolean) extends AbstractView[A] { + class DropWhile[A](underlying: SomeIterableOps[A]^, p: A => Boolean) extends AbstractView[A] { def iterator = underlying.iterator.dropWhile(p) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty @@ -248,7 +255,7 @@ object View extends IterableFactory[View] { /** A view that takes leading elements of the underlying collection. */ @SerialVersionUID(3L) - class Take[+A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { + class Take[+A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { def iterator = underlying.iterator.take(n) protected val normN = n max 0 override def knownSize = { @@ -260,7 +267,7 @@ 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] { + class TakeRight[+A](underlying: SomeIterableOps[A]^, n: Int) extends AbstractView[A] { def iterator = takeRightIterator(underlying.iterator, n) protected val normN = n max 0 override def knownSize = { @@ -273,15 +280,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 = 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 = underlying.iterator.scanLeft(z)(op) override def knownSize: Int = { val size = underlying.knownSize if (size >= 0) size + 1 else -1 @@ -291,7 +298,7 @@ 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] { + class Map[+A, +B](underlying: SomeIterableOps[A]^, f: A => B) extends AbstractView[B] { def iterator = underlying.iterator.map(f) override def knownSize = underlying.knownSize override def isEmpty: Boolean = underlying.isEmpty @@ -299,7 +306,7 @@ object View extends IterableFactory[View] { /** 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] { + class FlatMap[A, B](underlying: SomeIterableOps[A]^, f: A => IterableOnce[B]^) extends AbstractView[B] { def iterator = underlying.iterator.flatMap(f) override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize override def isEmpty: Boolean = iterator.isEmpty @@ -307,7 +314,7 @@ object View extends IterableFactory[View] { /** 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] { + class Collect[+A, B](underlying: SomeIterableOps[A]^, pf: PartialFunction[A, B]^) extends AbstractView[B] { def iterator = underlying.iterator.collect(pf) } @@ -315,7 +322,7 @@ object View extends IterableFactory[View] { * of the suffix collection or iterator. */ @SerialVersionUID(3L) - class Concat[A](prefix: SomeIterableOps[A], suffix: SomeIterableOps[A]) extends AbstractView[A] { + class Concat[A](prefix: SomeIterableOps[A]^, suffix: SomeIterableOps[A]^) extends AbstractView[A] { def iterator = prefix.iterator ++ suffix.iterator override def knownSize = { val prefixSize = prefix.knownSize @@ -333,7 +340,7 @@ object View extends IterableFactory[View] { * of another collection. */ @SerialVersionUID(3L) - class Zip[A, B](underlying: SomeIterableOps[A], other: Iterable[B]) extends AbstractView[(A, B)] { + class Zip[A, B](underlying: SomeIterableOps[A]^, other: Iterable[B]^) extends AbstractView[(A, B)] { def iterator = underlying.iterator.zip(other) override def knownSize = { val s1 = underlying.knownSize @@ -350,7 +357,7 @@ 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)] { + 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) override def knownSize = { val s1 = underlying.knownSize @@ -364,8 +371,8 @@ 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 = new Concat(underlying, new View.Single(elem)).iterator override def knownSize: Int = { val size = underlying.knownSize if (size >= 0) size + 1 else -1 @@ -375,8 +382,8 @@ 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 = new Concat(new View.Single(elem), underlying).iterator override def knownSize: Int = { val size = underlying.knownSize if (size >= 0) size + 1 else -1 @@ -385,8 +392,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 = { @@ -404,28 +411,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]^{this} = 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)]^{this} = 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]^{this} = underlying.iterator.padTo(len, elem) override def knownSize: Int = { val size = underlying.knownSize @@ -434,7 +441,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 @@ -442,7 +449,7 @@ 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](private[this] var underlying: Iterator[A]^, maxlen: Int) extends AbstractIterator[A] { private[this] var len: Int = -1 private[this] var pos: Int = 0 private[this] var buf: ArrayBuffer[AnyRef] = _ @@ -478,7 +485,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 @@ -488,7 +495,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 @@ -497,7 +504,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](private[this] var 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/library/src/scala/collection/WithFilter.scala b/library/src/scala/collection/WithFilter.scala index da65ba6fab27..fa4cf28e43a4 100644 --- a/library/src/scala/collection/WithFilter.scala +++ b/library/src/scala/collection/WithFilter.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking /** A template trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods * of trait `Iterable`. @@ -34,7 +35,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 @@ -46,7 +47,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. * @@ -67,6 +68,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/library/src/scala/collection/concurrent/Map.scala b/library/src/scala/collection/concurrent/Map.scala index 818fcda2a510..2269816f49b6 100644 --- a/library/src/scala/collection/concurrent/Map.scala +++ b/library/src/scala/collection/concurrent/Map.scala @@ -14,6 +14,8 @@ package scala package collection.concurrent import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.tailrec /** A template trait for mutable maps that allow concurrent access. diff --git a/library/src/scala/collection/concurrent/TrieMap.scala b/library/src/scala/collection/concurrent/TrieMap.scala index 4e3916c6981c..a29eb902afb4 100644 --- a/library/src/scala/collection/concurrent/TrieMap.scala +++ b/library/src/scala/collection/concurrent/TrieMap.scala @@ -15,6 +15,8 @@ package collection package concurrent import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.concurrent.atomic._ import scala.{unchecked => uc} import scala.annotation.tailrec @@ -1016,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 /////////////////////////////////////////////////////////////////// @@ -1042,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]) @@ -1068,7 +1070,7 @@ object TrieMap extends MapFactory[TrieMap] { } // non-final as an extension point for parallel collections -private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends AbstractIterator[(K, V)] { +private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends AbstractIterator[(K, V)] { self => private val stack = new Array[Array[BasicNode]](7) private val stackpos = new Array[Int](7) private var depth = -1 diff --git a/library/src/scala/collection/convert/AsJavaConverters.scala b/library/src/scala/collection/convert/AsJavaConverters.scala index f82546e251a7..079847776368 100644 --- a/library/src/scala/collection/convert/AsJavaConverters.scala +++ b/library/src/scala/collection/convert/AsJavaConverters.scala @@ -15,6 +15,8 @@ package collection package convert import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.{concurrent => juc} import java.{lang => jl, util => ju} diff --git a/library/src/scala/collection/convert/AsJavaExtensions.scala b/library/src/scala/collection/convert/AsJavaExtensions.scala index 406ad7e8b82f..67f127d9e042 100644 --- a/library/src/scala/collection/convert/AsJavaExtensions.scala +++ b/library/src/scala/collection/convert/AsJavaExtensions.scala @@ -15,6 +15,8 @@ package collection package convert import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.{concurrent => juc} import java.{lang => jl, util => ju} diff --git a/library/src/scala/collection/convert/AsScalaConverters.scala b/library/src/scala/collection/convert/AsScalaConverters.scala index dac9b9484369..e2fa0f39bfef 100644 --- a/library/src/scala/collection/convert/AsScalaConverters.scala +++ b/library/src/scala/collection/convert/AsScalaConverters.scala @@ -15,6 +15,9 @@ package collection package convert import scala.language.`2.13` +import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure + import java.util.{concurrent => juc} import java.{lang => jl, util => ju} @@ -40,7 +43,7 @@ trait AsScalaConverters { */ def asScala[A](i: ju.Iterator[A]): Iterator[A] = i match { case null => null - case wrapper: IteratorWrapper[A @uc] => wrapper.underlying + case wrapper: IteratorWrapper[A @uc] => wrapper.underlying.unsafeAssumePure // TODO: Remove when pattern matching recognizes this is safe case _ => new JIteratorWrapper(i) } @@ -58,7 +61,7 @@ trait AsScalaConverters { */ def asScala[A](e: ju.Enumeration[A]): Iterator[A] = e match { case null => null - case wrapper: IteratorWrapper[A @uc] => wrapper.underlying + case wrapper: IteratorWrapper[A @uc] => wrapper.underlying.unsafeAssumePure // TODO: Remove when pattern matching recognizes this is safe case _ => new JEnumerationWrapper(e) } @@ -76,7 +79,7 @@ trait AsScalaConverters { */ def asScala[A](i: jl.Iterable[A]): Iterable[A] = i match { case null => null - case wrapper: IterableWrapper[A @uc] => wrapper.underlying + case wrapper: IterableWrapper[A @uc] => wrapper.underlying.unsafeAssumePure // TODO: Remove when pattern matching recognizes this is safe case _ => new JIterableWrapper(i) } @@ -91,7 +94,7 @@ trait AsScalaConverters { */ def asScala[A](c: ju.Collection[A]): Iterable[A] = c match { case null => null - case wrapper: IterableWrapper[A @uc] => wrapper.underlying + case wrapper: IterableWrapper[A @uc] => wrapper.underlying.unsafeAssumePure // TODO: Remove when pattern matching recognizes this is safe case _ => new JCollectionWrapper(c) } diff --git a/library/src/scala/collection/convert/AsScalaExtensions.scala b/library/src/scala/collection/convert/AsScalaExtensions.scala index 65f017495280..3ef08f0690f3 100644 --- a/library/src/scala/collection/convert/AsScalaExtensions.scala +++ b/library/src/scala/collection/convert/AsScalaExtensions.scala @@ -15,6 +15,8 @@ package collection package convert import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.{concurrent => juc} import java.{lang => jl, util => ju} diff --git a/library/src/scala/collection/convert/ImplicitConversions.scala b/library/src/scala/collection/convert/ImplicitConversions.scala index ef72a79d5795..b2ebd48f16e9 100644 --- a/library/src/scala/collection/convert/ImplicitConversions.scala +++ b/library/src/scala/collection/convert/ImplicitConversions.scala @@ -15,6 +15,8 @@ package collection package convert import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.{concurrent => juc} import java.{lang => jl, util => ju} diff --git a/library/src/scala/collection/convert/JavaCollectionWrappers.scala b/library/src/scala/collection/convert/JavaCollectionWrappers.scala index 1679491efcb0..5058f93fc48f 100644 --- a/library/src/scala/collection/convert/JavaCollectionWrappers.scala +++ b/library/src/scala/collection/convert/JavaCollectionWrappers.scala @@ -15,6 +15,8 @@ package collection package convert import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.{concurrent => juc} import java.util.{NavigableMap} import java.{lang => jl, util => ju} @@ -29,7 +31,7 @@ import scala.util.control.ControlThrowable // not private[convert] because `WeakHashMap` uses JMapWrapper private[collection] object JavaCollectionWrappers extends Serializable { @SerialVersionUID(3L) - class IteratorWrapper[A](val underlying: Iterator[A]) extends ju.Iterator[A] with ju.Enumeration[A] with Serializable { + class IteratorWrapper[A](val underlying: Iterator[A]^) extends ju.Iterator[A] with ju.Enumeration[A] with Serializable { def hasNext = underlying.hasNext def next() = underlying.next() def hasMoreElements = underlying.hasNext @@ -65,14 +67,14 @@ private[collection] object JavaCollectionWrappers extends Serializable { } trait IterableWrapperTrait[A] extends ju.AbstractCollection[A] { - val underlying: Iterable[A] + val underlying: Iterable[A]^ def size = underlying.size - override def iterator: IteratorWrapper[A] = new IteratorWrapper(underlying.iterator) + override def iterator: IteratorWrapper[A]^{this} = 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 { + 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 @@ -151,7 +153,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(_)) } @@ -160,7 +162,7 @@ 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 diff --git a/library/src/scala/collection/convert/StreamExtensions.scala b/library/src/scala/collection/convert/StreamExtensions.scala index 4457989ead40..5e70ed1b4fd0 100644 --- a/library/src/scala/collection/convert/StreamExtensions.scala +++ b/library/src/scala/collection/convert/StreamExtensions.scala @@ -13,6 +13,8 @@ package scala.collection.convert import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.Spliterator import java.util.stream._ import java.{lang => jl} diff --git a/library/src/scala/collection/generic/BitOperations.scala b/library/src/scala/collection/generic/BitOperations.scala index 39aa29d1daf9..a0a2806bd0dc 100644 --- a/library/src/scala/collection/generic/BitOperations.scala +++ b/library/src/scala/collection/generic/BitOperations.scala @@ -14,6 +14,7 @@ package scala.collection package generic import scala.language.`2.13` +import language.experimental.captureChecking /** Some bit operations. * diff --git a/library/src/scala/collection/generic/CommonErrors.scala b/library/src/scala/collection/generic/CommonErrors.scala index 3ced8e3debbf..c7cb23a3d112 100644 --- a/library/src/scala/collection/generic/CommonErrors.scala +++ b/library/src/scala/collection/generic/CommonErrors.scala @@ -14,6 +14,7 @@ package scala.collection package generic import scala.language.`2.13` +import language.experimental.captureChecking /** Some precomputed common errors to reduce the generated code size. */ diff --git a/library/src/scala/collection/generic/DefaultSerializationProxy.scala b/library/src/scala/collection/generic/DefaultSerializationProxy.scala index 056e53b6f882..d6b5e4e47693 100644 --- a/library/src/scala/collection/generic/DefaultSerializationProxy.scala +++ b/library/src/scala/collection/generic/DefaultSerializationProxy.scala @@ -15,6 +15,8 @@ package scala.collection.generic import java.io.{ObjectInputStream, ObjectOutputStream} import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.{Factory, Iterable} import scala.collection.mutable.Builder @@ -26,7 +28,7 @@ import scala.collection.mutable.Builder * additional state required to create the proper `Builder` needs to be captured by the `factory`. */ @SerialVersionUID(3L) -final class DefaultSerializationProxy[A](factory: Factory[A, Any], @transient private[this] val coll: Iterable[A]) extends Serializable { +final class DefaultSerializationProxy[A](factory: Factory[A, Any], @transient private[this] val coll: Iterable[A]^) extends Serializable { @transient protected var builder: Builder[A, Any] = _ @@ -75,8 +77,8 @@ private[collection] case object SerializeEnd * it directly without using this trait if you need a non-standard factory or if you want to use a different * serialization scheme. */ -transparent trait DefaultSerializable extends Serializable { this: scala.collection.Iterable[_] => - protected[this] def writeReplace(): AnyRef = { +transparent trait DefaultSerializable extends Serializable { this: scala.collection.Iterable[_]^ => + protected[this] def writeReplace(): AnyRef^{this} = { val f: Factory[Any, Any] = this match { case it: scala.collection.SortedMap[_, _] => it.sortedMapFactory.sortedMapFactory[Any, Any](using it.ordering.asInstanceOf[Ordering[Any]]).asInstanceOf[Factory[Any, Any]] case it: scala.collection.Map[_, _] => it.mapFactory.mapFactory[Any, Any].asInstanceOf[Factory[Any, Any]] diff --git a/library/src/scala/collection/generic/IsIterable.scala b/library/src/scala/collection/generic/IsIterable.scala index fd5db475536f..0b80203037fc 100644 --- a/library/src/scala/collection/generic/IsIterable.scala +++ b/library/src/scala/collection/generic/IsIterable.scala @@ -14,6 +14,7 @@ package scala.collection package generic import scala.language.`2.13` +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/library/src/scala/collection/generic/IsIterableOnce.scala b/library/src/scala/collection/generic/IsIterableOnce.scala index a5c2c4889722..bced6e190206 100644 --- a/library/src/scala/collection/generic/IsIterableOnce.scala +++ b/library/src/scala/collection/generic/IsIterableOnce.scala @@ -15,6 +15,7 @@ package collection package generic import scala.language.`2.13` +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/library/src/scala/collection/generic/IsMap.scala b/library/src/scala/collection/generic/IsMap.scala index 47eac5587f11..5b5a988792c0 100644 --- a/library/src/scala/collection/generic/IsMap.scala +++ b/library/src/scala/collection/generic/IsMap.scala @@ -14,6 +14,8 @@ package scala.collection package generic import scala.language.`2.13` +import language.experimental.captureChecking + import IsMap.Tupled import scala.collection.immutable.{IntMap, LongMap} diff --git a/library/src/scala/collection/generic/IsSeq.scala b/library/src/scala/collection/generic/IsSeq.scala index 2707ce988e34..04a94c5e5da0 100644 --- a/library/src/scala/collection/generic/IsSeq.scala +++ b/library/src/scala/collection/generic/IsSeq.scala @@ -14,6 +14,8 @@ package scala.collection package generic import scala.language.`2.13` +import language.experimental.captureChecking + import scala.reflect.ClassTag /** Type class witnessing that a collection representation type `Repr` has @@ -69,7 +71,7 @@ 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 + protected[this] def fromSpecific(coll: IterableOnce[Char]^): String = coll.iterator.mkString def iterableFactory: IterableFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged override def empty: String = "" protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder @@ -94,7 +96,7 @@ object IsSeq { def length: Int = a.length def toIterable: Iterable[A] = mutable.ArraySeq.make(a) protected def coll: Array[A] = a - protected def fromSpecific(coll: IterableOnce[A]): Array[A] = Array.from(coll) + protected def fromSpecific(coll: IterableOnce[A]^): Array[A] = Array.from(coll) def iterableFactory: IterableFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged override def empty: Array[A] = Array.empty[A] protected def newSpecificBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder diff --git a/library/src/scala/collection/generic/Subtractable.scala b/library/src/scala/collection/generic/Subtractable.scala index 2e06819b6832..87c8f57c79d2 100644 --- a/library/src/scala/collection/generic/Subtractable.scala +++ b/library/src/scala/collection/generic/Subtractable.scala @@ -15,6 +15,7 @@ package collection package generic import scala.language.`2.13` +import language.experimental.captureChecking /** This trait represents collection-like objects that can be reduced * using a '+' operator. It defines variants of `-` and `--` @@ -60,5 +61,5 @@ trait Subtractable[A, +Repr <: Subtractable[A, Repr]] { self => * @return a new $coll that contains all elements of the current $coll * except one less occurrence of each of the elements of `elems`. */ - def --(xs: IterableOnce[A]): Repr = (repr /: xs.iterator) (_ - _) + def --(xs: IterableOnce[A]^): Repr = (repr /: xs.iterator) (_ - _) } diff --git a/library/src/scala/collection/generic/package.scala b/library/src/scala/collection/generic/package.scala index 0dc855d81d54..91181e0f7751 100644 --- a/library/src/scala/collection/generic/package.scala +++ b/library/src/scala/collection/generic/package.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking package object generic { @deprecated("Clearable was moved from collection.generic to collection.mutable", "2.13.0") diff --git a/library/src/scala/collection/immutable/ArraySeq.scala b/library/src/scala/collection/immutable/ArraySeq.scala index 9cd2700779fb..76e6097fca50 100644 --- a/library/src/scala/collection/immutable/ArraySeq.scala +++ b/library/src/scala/collection/immutable/ArraySeq.scala @@ -14,6 +14,8 @@ package scala.collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import java.util.Arrays import scala.annotation.unchecked.uncheckedVariance @@ -39,7 +41,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 caps.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 @@ -125,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 @@ -148,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 @@ -172,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 => @@ -278,7 +281,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)) } diff --git a/library/src/scala/collection/immutable/BitSet.scala b/library/src/scala/collection/immutable/BitSet.scala index c454727fe4b9..176c31794621 100644 --- a/library/src/scala/collection/immutable/BitSet.scala +++ b/library/src/scala/collection/immutable/BitSet.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import BitSetOps.{LogWL, updateArray} import mutable.Builder import scala.annotation.{implicitNotFound, nowarn} @@ -38,7 +40,7 @@ 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 @@ -71,16 +73,16 @@ sealed abstract class BitSet override def map[B](f: Int => B)(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = super[StrictOptimizedSortedSetOps].map(f) - override def flatMap(f: Int => IterableOnce[Int]): BitSet = strictOptimizedFlatMap(newSpecificBuilder, f) - override def flatMap[B](f: Int => IterableOnce[B])(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = + override def flatMap(f: Int => IterableOnce[Int]^): BitSet = strictOptimizedFlatMap(newSpecificBuilder, f) + override def flatMap[B](f: Int => IterableOnce[B]^)(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = super[StrictOptimizedSortedSetOps].flatMap(f) - override def collect(pf: PartialFunction[Int, Int]): BitSet = strictOptimizedCollect(newSpecificBuilder, pf) - override def collect[B](pf: scala.PartialFunction[Int, B])(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = + override def collect(pf: PartialFunction[Int, Int]^): BitSet = strictOptimizedCollect(newSpecificBuilder, pf) + override def collect[B](pf: scala.PartialFunction[Int, B]^)(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = super[StrictOptimizedSortedSetOps].collect(pf) // necessary for disambiguation - override def zip[B](that: scala.IterableOnce[B])(implicit @implicitNotFound(collection.BitSet.zipOrdMsg) ev: Ordering[(Int, B)]): SortedSet[(Int, B)] = + override def zip[B](that: scala.IterableOnce[B]^)(implicit @implicitNotFound(collection.BitSet.zipOrdMsg) ev: Ordering[(Int, B)]): SortedSet[(Int, B)] = super.zip(that) protected[this] def writeReplace(): AnyRef = new BitSet.SerializationProxy(this) @@ -95,7 +97,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/library/src/scala/collection/immutable/ChampCommon.scala b/library/src/scala/collection/immutable/ChampCommon.scala index 899525e822a6..86b212de72f9 100644 --- a/library/src/scala/collection/immutable/ChampCommon.scala +++ b/library/src/scala/collection/immutable/ChampCommon.scala @@ -13,6 +13,8 @@ package scala.collection.immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.AbstractIterator import java.lang.Integer.bitCount import java.lang.Math.ceil diff --git a/library/src/scala/collection/immutable/HashMap.scala b/library/src/scala/collection/immutable/HashMap.scala index eefdf6b6adbb..96d1d9cc0d8e 100644 --- a/library/src/scala/collection/immutable/HashMap.scala +++ b/library/src/scala/collection/immutable/HashMap.scala @@ -14,6 +14,8 @@ package scala package collection.immutable import scala.language.`2.13` +import language.experimental.captureChecking + import java.lang.Integer.bitCount import java.lang.System.arraycopy @@ -162,7 +164,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 { @@ -385,7 +387,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 { @@ -2200,7 +2202,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() @@ -2364,7 +2366,7 @@ 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] => diff --git a/library/src/scala/collection/immutable/HashSet.scala b/library/src/scala/collection/immutable/HashSet.scala index 8ce8035fd015..65dca3dbba79 100644 --- a/library/src/scala/collection/immutable/HashSet.scala +++ b/library/src/scala/collection/immutable/HashSet.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import java.lang.Integer.{bitCount, numberOfTrailingZeros} import java.lang.System.arraycopy @@ -92,7 +94,7 @@ final class HashSet[A] private[immutable](private[immutable] val rootNode: Bitma newHashSetOrThis(newRootNode) } - override def concat(that: IterableOnce[A]): HashSet[A] = + override def concat(that: IterableOnce[A]^): HashSet[A] = that match { case hs: HashSet[A] => if (isEmpty) hs @@ -277,7 +279,7 @@ final class HashSet[A] private[immutable](private[immutable] val rootNode: Bitma * * That is, this method is safe to call on published sets because it does not mutate `this` */ - private[this] def removedAllWithShallowMutations(that: IterableOnce[A]): HashSet[A] = { + private[this] def removedAllWithShallowMutations(that: IterableOnce[A]^): HashSet[A] = { val iter = that.iterator var curr = rootNode while (iter.hasNext) { @@ -306,7 +308,7 @@ final class HashSet[A] private[immutable](private[immutable] val rootNode: Bitma this } - override def removedAll(that: IterableOnce[A]): HashSet[A] = that match { + override def removedAll(that: IterableOnce[A]^): HashSet[A] = that match { case set: scala.collection.Set[A] => diff(set) case range: Range if range.length > size => filter { @@ -1937,7 +1939,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] @@ -2077,7 +2079,7 @@ 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] => diff --git a/library/src/scala/collection/immutable/IntMap.scala b/library/src/scala/collection/immutable/IntMap.scala index 1728da6c5710..6705091640b8 100644 --- a/library/src/scala/collection/immutable/IntMap.scala +++ b/library/src/scala/collection/immutable/IntMap.scala @@ -14,6 +14,8 @@ package scala.collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.generic.{BitOperations, DefaultSerializationProxy} import scala.collection.mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec @@ -53,7 +55,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] { @@ -90,13 +92,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] } @@ -181,9 +183,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) @@ -326,12 +328,12 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] def map[V2](f: ((Int, T)) => (Int, V2)): IntMap[V2] = intMapFrom(new View.Map(this, f)) - def flatMap[V2](f: ((Int, T)) => IterableOnce[(Int, V2)]): IntMap[V2] = intMapFrom(new View.FlatMap(this, f)) + 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/library/src/scala/collection/immutable/Iterable.scala b/library/src/scala/collection/immutable/Iterable.scala index 0691663e7e4d..65f95ad87a27 100644 --- a/library/src/scala/collection/immutable/Iterable.scala +++ b/library/src/scala/collection/immutable/Iterable.scala @@ -13,6 +13,8 @@ package scala.collection.immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.{IterableFactory, IterableFactoryDefaults} /** A trait for collections that are guaranteed immutable. @@ -31,7 +33,7 @@ trait Iterable[+A] extends collection.Iterable[A] @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/library/src/scala/collection/immutable/LazyList.scala b/library/src/scala/collection/immutable/LazyList.scala index bcf5f5df17a8..823144a19338 100644 --- a/library/src/scala/collection/immutable/LazyList.scala +++ b/library/src/scala/collection/immutable/LazyList.scala @@ -262,6 +262,9 @@ import scala.runtime.Statics * @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. + * @note Under Capture Checking, LazyList is unsound with regards to lazy/strict separation of collections. + * LazyList as-is will not be capture checked and might be deprecated in the future. + * Use LazyListIterable instead. */ @SerialVersionUID(4L) final class LazyList[+A] private (lazyState: AnyRef /* EmptyMarker.type | () => LazyList[A] */) diff --git a/library/src/scala/collection/immutable/LazyListIterable.scala b/library/src/scala/collection/immutable/LazyListIterable.scala new file mode 100644 index 000000000000..f1d14bbb1fad --- /dev/null +++ b/library/src/scala/collection/immutable/LazyListIterable.scala @@ -0,0 +1,1478 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. dba Akka + * + * 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 scala.language.`2.13` +import language.experimental.captureChecking + +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 + +/** This class implements an immutable linked list. We call it "lazy" + * because it computes its elements only when they are needed. + * + * Elements are memoized; that is, the value of each element is computed at most once. + * + * Elements are computed in order and are never skipped. + * As a consequence, 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. + * We say that it is lazy in its head. + * If you have tested that it is non-empty, + * then you also know that the head has been computed. + * + * It is also lazy in its tail, which is also a `LazyListIterable`. + * You don't know whether the tail is empty until it is "forced", which is to say, + * until an element of the tail is computed. + * + * These important properties of `LazyListIterable` depend on its construction using `#::` (or `#:::`). + * That operator is analogous to the "cons" of a strict `List`, `::`. + * It is "right-associative", so that the collection goes on the "right", + * and the element on the left of the operator is prepended to the collection. + * However, unlike the cons of a strict `List`, `#::` is lazy in its parameter, + * which is the element prepended to the left, and also lazy in its right-hand side, + * which is the `LazyListIterable` being prepended to. + * (That is accomplished by implicitly wrapping the `LazyListIterable`, as shown in the Scaladoc.) + * + * Other combinators from the collections API do not preserve this laziness. + * In particular, `++`, or `concat`, is "eager" or "strict" in its parameter + * and should not be used to compose `LazyListIterable`s. + * + * A `LazyListIterable` may be infinite. For example, `LazyListIterable.from(0)` contains + * all of the natural numbers `0`, `1`, `2`, ... For infinite sequences, + * some methods (such as `count`, `sum`, `max` or `min`) will not terminate. + * + * Here is an example showing the Fibonacci sequence, + * which may be evaluated to an arbitrary number of elements: + * + * {{{ + * 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) + * println { + * fibs.take(5).mkString(", ") + * } + * } + * // 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 + * import scala.util.chaining._ + * object Main extends App { + * val fibs: LazyListIterable[BigInt] = + * BigInt(0) #:: BigInt(1) #:: + * fibs.zip(fibs.tail).map(n => (n._1 + n._2) + * .tap(sum => println(s"Adding ${n._1} and ${n._2} => $sum"))) + * fibs.take(5).foreach(println) + * fibs.take(6).foreach(println) + * } + * + * // prints + * // + * // 0 + * // 1 + * // Adding 0 and 1 => 1 + * // 1 + * // Adding 1 and 1 => 2 + * // 2 + * // Adding 1 and 2 => 3 + * // 3 + * + * // And then prints + * // + * // 0 + * // 1 + * // 1 + * // 2 + * // 3 + * // Adding 2 and 3 => 5 + * // 5 + * }}} + * + * Note that the definition of `fibs` uses `val` not `def`. + * Memoization of the `LazyListIterable` requires us to retain a reference to the computed values. + * + * `LazyListIterable` is considered an immutable data structure, even though its elements are computed on demand. + * Once the values are memoized they do not change. + * Moreover, the `LazyListIterable` itself is defined once and references to it are interchangeable. + * Values that have yet to be memoized still "exist"; they simply haven't been computed yet. + * + * Memoization can be a source of memory leaks and must be used with caution. + * It avoids recomputing elements of the list, but if a reference to the head + * is retained unintentionally, then all elements will be retained. + * + * The caveat that all elements are computed in order means + * that some operations, such as [[drop]], [[dropWhile]], [[flatMap]] or [[collect]], + * may process a large number of intermediate elements before returning. + * + * Here's an example that illustrates these behaviors. + * Let's begin with an iteration of the natural numbers. + * + * {{{ + * // 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 we retain only a reference to its Iterator. + * // That allows the LazyListIterable to be garbage collected. + * // Using `def` to produce the LazyListIterable in a method ensures + * // that no val is holding onto the head, as 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 is initially unknown. + * Once any of those are evaluated, they are all known, though if the tail is + * built with `#::` or `#:::`, its content still isn't evaluated. Instead, evaluating + * the tail's content is deferred until the tail's empty status, head or tail is + * evaluated. + * + * Delaying the evaluation of whether a LazyListIterable is empty 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!) do any of the elements get 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" + * }}} + * + * ---- + * + * You may sometimes encounter an exception like the following: + * + * {{{ + * java.lang.RuntimeException: "LazyListIterable evaluation depends on its own result (self-reference); see docs for more info + * }}} + * + * This exception occurs when a `LazyListIterable` is attempting to derive its next element + * from itself, and is attempting to read the element currently being evaluated. + * As a trivial example: + * + * {{{ + * lazy val a: LazyListIterable[Int] = 1 #:: 2 #:: a.filter(_ > 2) + * }}} + * + * When attempting to evaluate the third element of `a`, it will skip the first two + * elements and read the third, but that element is already being evaluated. This is + * often caused by a subtle logic error; in this case, using `>=` in the `filter` + * would fix the error. + * + * @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#lazylistsIterable "Scala's Collection Library overview"]] + * section on `LazyListIterables` for a summary. + * @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(4L) +final class LazyListIterable[+A] private (lazyState: LazyListIterable.EmptyMarker.type | (() => LazyListIterable[A]^) /* EmptyMarker.type | () => LazyListIterable[A] */) + extends Iterable[A] + with collection.SeqOps[A, LazyListIterable, LazyListIterable[A]] + with IterableFactoryDefaults[A, LazyListIterable] + with Serializable { self: LazyListIterable[A]^ => + import LazyListIterable._ + + // kount() // LazyListTest.countAlloc + + private def this(head: A, tail: LazyListIterable[A]^) = { + this(LazyListIterable.EmptyMarker) + _head = head + _tail = caps.unsafe.unsafeAssumePure(tail) // SAFETY: we initialize LazyListIterable capturing tail + } + + // used to synchronize lazy state evaluation + // after initialization (`_head ne Uninitialized`) + // - `null` if this is an empty lazy list + // - `head: A` otherwise (can be `null`, `_tail == null` is used to test emptiness) + @volatile private[this] var _head: Any /* Uninitialized | A */ = + if (lazyState eq EmptyMarker) null else Uninitialized + + // when `_head eq Uninitialized` + // - `lazySate: () => LazyListIterable[A]` + // - MidEvaluation while evaluating lazyState + // when `_head ne Uninitialized` + // - `null` if this is an empty lazy list + // - `tail: LazyListIterable[A]` otherwise + private[this] var _tail: AnyRef^{this} /* () => LazyListIterable[A] | MidEvaluation.type | LazyListIterable[A] */ = + if (lazyState eq EmptyMarker) null else lazyState + + private def rawHead: Any = _head + private def rawTail: AnyRef^{this} = _tail + + @inline private def isEvaluated: Boolean = _head.asInstanceOf[AnyRef] ne Uninitialized + + private def initState(): Unit = synchronized { + if (!isEvaluated) { + // if it's already mid-evaluation, we're stuck in an infinite + // self-referential loop (also it's empty) + if (_tail eq MidEvaluation) + throw new RuntimeException( + "LazyListIterable evaluation depends on its own result (self-reference); see docs for more info") + + val fun = _tail.asInstanceOf[() ->{this} LazyListIterable[A]^] + _tail = MidEvaluation + val l = + // `fun` returns a LazyListIterable that represents the state (head/tail) of `this`. We call `l.evaluated` to ensure + // `l` is initialized, to prevent races when reading `rawTail` / `rawHead` below. + // Often, lazy lists are created with `newLL(eagerCons(...))` so `l` is already initialized, but `newLL` also + // accepts non-evaluated lazy lists. + try fun().evaluated + // restore `fun` in finally so we can try again later if an exception was thrown (similar to lazy val) + finally _tail = fun + _tail = l.rawTail + _head = l.rawHead + } + } + + @tailrec private def evaluated: LazyListIterable[A]^{this} = + if (isEvaluated) { + if (_tail == null) Empty + else this + } else { + initState() + evaluated + } + + override def iterableFactory: IterableFactory[LazyListIterable] = LazyListIterable + + // NOTE: `evaluated; this eq Empty` would be wrong. Deserialization of `Empty` creates a new + // instance with `null` fields, but the `evaluated` method always returns the canonical `Empty`. + @inline override def isEmpty: Boolean = evaluated eq Empty + + /** @inheritdoc + * + * $preservesLaziness + */ + override def knownSize: Int = if (knownIsEmpty) 0 else -1 + + override def head: A = + // inlined `isEmpty` to make it clear that `rawHead` below is initialized + if (evaluated eq Empty) throw new NoSuchElementException("head of empty lazy list") + else rawHead.asInstanceOf[A] + + override def tail: LazyListIterable[A]^{this} = + // inlined `isEmpty` to make it clear that `rawTail` below is initialized + if (evaluated eq Empty) throw new UnsupportedOperationException("tail of empty lazy list") + else rawTail.asInstanceOf[LazyListIterable[A]] + + /* Same implementation as of LinearSeq */ + override def length: Int = { + var these: LazyListIterable[A]^{this} = coll + var len = 0 + while (these.nonEmpty) { + len += 1 + these = these.tail + } + len + } + + /* Same implementation as of LinearSeq */ + // `apply` is defined in terms of `drop`, which is in turn defined in + // terms of `tail`. + @throws[IndexOutOfBoundsException] + override def apply(n: Int): A = { + if (n < 0) throw new IndexOutOfBoundsException(n.toString) + val skipped = drop(n) + if (skipped.isEmpty) throw new IndexOutOfBoundsException(n.toString) + skipped.head + } + + @inline private[this] def knownIsEmpty: Boolean = isEvaluated && isEmpty + @inline private def knownNonEmpty: Boolean = isEvaluated && !isEmpty + + /** 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) + + // LazyListIterable.Empty doesn't use the SerializationProxy + protected[this] def writeReplace(): AnyRef^{this} = + if (knownNonEmpty) new 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 // don't recompute the LazyListIterable + case coll if coll.knownSize == 0 => Empty + case coll => eagerHeadFromIterator(coll.iterator) + } + else eagerCons(head, tail lazyAppendedAll suffix) + } + + /** @inheritdoc + * + * $preservesLaziness + * + * $appendStackSafety + */ + override def appendedAll[B >: A](suffix: IterableOnce[B]^): LazyListIterable[B]^{this, suffix} = + if (knownIsEmpty) LazyListIterable.from(suffix) + else lazyAppendedAll(suffix) + + /** @inheritdoc + * + * $preservesLaziness + * + * $appendStackSafety + */ + override def appended[B >: A](elem: B): LazyListIterable[B]^{this} = + if (knownIsEmpty) eagerCons(elem, Empty) + else lazyAppendedAll(Iterator.single(elem)) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def scanLeft[B](z: B)(op: (B, A) => B): LazyListIterable[B]^{this, op} = + if (knownIsEmpty) eagerCons(z, Empty) + else scanLeftImpl(z)(op) + + private def scanLeftImpl[B](z: B)(op: (B, A) => B): LazyListIterable[B]^{this, op} = + eagerCons( + z, + newLL { + if (isEmpty) Empty + else tail.scanLeftImpl(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 (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") + else { + var reducedRes: B = head + var left: LazyListIterable[A]^{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 p: (LazyListIterable[Either[A1, A2]]^{this, f}, LazyListIterable[Either[A1, A2]]^{this, f}) = map(f).partition(_.isLeft) + (p._1.map(_.asInstanceOf[Left[A1, _]].value), p._2.map(_.asInstanceOf[Right[_, A2]].value)) + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def filter(pred: A => Boolean): LazyListIterable[A]^{this, pred} = + if (knownIsEmpty) Empty + else filterImpl(this, pred, isFlipped = false) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def filterNot(pred: A => Boolean): LazyListIterable[A]^{this, pred} = + if (knownIsEmpty) Empty + else 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 + */ + override def prepended[B >: A](elem: B): LazyListIterable[B]^{this} = eagerCons(elem, this) + + /** @inheritdoc + * + * $preservesLaziness + */ + override 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(eagerHeadPrependIterator(prefix.iterator)(this)) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def map[B](f: A => B): LazyListIterable[B]^{this, f} = + if (knownIsEmpty) Empty + else mapImpl(f) + + /** @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) Empty + else eagerCons(f(head), tail.mapImpl(f)) + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def collect[B](pf: PartialFunction[A, B]^): LazyListIterable[B]^{this, pf} = + if (knownIsEmpty) Empty + else 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, 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) Empty + else 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 (knownIsEmpty || that.knownSize == 0) Empty + else newLL(eagerHeadZipImpl(that.iterator)) + + private def eagerHeadZipImpl[B](it: Iterator[B]^): LazyListIterable[(A, B)]^{this, it} = + if (isEmpty || !it.hasNext) Empty + else eagerCons((head, it.next()), newLL { tail eagerHeadZipImpl 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 (knownIsEmpty) { + if (that.knownSize == 0) Empty + else LazyListIterable.continually(thisElem) zip that + } else { + if (that.knownSize == 0) zip(LazyListIterable.continually(thatElem)) + else newLL(eagerHeadZipAllImpl(that.iterator, thisElem, thatElem)) + } + } + + private def eagerHeadZipAllImpl[A1 >: A, B](it: Iterator[B]^, thisElem: A1, thatElem: B): LazyListIterable[(A1, B)]^{this, it} = { + if (it.hasNext) { + if (isEmpty) eagerCons((thisElem, it.next()), newLL { LazyListIterable.continually(thisElem) eagerHeadZipImpl it }) + else eagerCons((head, it.next()), newLL { tail.eagerHeadZipAllImpl(it, thisElem, thatElem) }) + } else { + if (isEmpty) Empty + else eagerCons((head, thatElem), 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, 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) Empty + else 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) Empty + else dropWhileImpl(this, p) + + /** @inheritdoc + * + * $initiallyLazy + */ + override def dropRight(n: Int): LazyListIterable[A]^{this} = { + if (n <= 0) this + else if (knownIsEmpty) Empty + else newLL { + var scout: LazyListIterable[A]^{this} = this + var remaining = n + // advance scout n elements ahead (or until empty) + while (remaining > 0 && !scout.isEmpty) { + remaining -= 1 + scout = scout.tail + } + eagerHeadDropRightImpl(scout) + } + } + + private def eagerHeadDropRightImpl(scout: LazyListIterable[_]^): LazyListIterable[A]^{this, scout} = + if (scout.isEmpty) Empty + else eagerCons(head, newLL(tail.eagerHeadDropRightImpl(scout.tail))) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def take(n: Int): LazyListIterable[A]^{this} = + if (knownIsEmpty) Empty + else takeImpl(n) + + private def takeImpl(n: Int): LazyListIterable[A]^{this} = { + if (n <= 0) Empty + else newLL { + if (isEmpty) Empty + else eagerCons(head, tail.takeImpl(n - 1)) + } + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override def takeWhile(p: A => Boolean): LazyListIterable[A]^{this, p} = + if (knownIsEmpty) Empty + else takeWhileImpl(p) + + private def takeWhileImpl(p: A => Boolean): LazyListIterable[A]^{this, p} = + newLL { + if (isEmpty || !p(head)) Empty + else eagerCons(head, tail.takeWhileImpl(p)) + } + + /** @inheritdoc + * + * $initiallyLazy + */ + override def takeRight(n: Int): LazyListIterable[A]^{this} = + if (n <= 0 || knownIsEmpty) Empty + else 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 + */ + override def reverse: LazyListIterable[A]^{this} = reverseOnto(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]^{this, tl} = + if (isEmpty) tl + else tail.reverseOnto(newLL(eagerCons(head, tl))) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def diff[B >: A](that: collection.Seq[B]): LazyListIterable[A]^{this} = + if (knownIsEmpty) Empty + else super.diff(that) + + /** @inheritdoc + * + * $preservesLaziness + */ + override def intersect[B >: A](that: collection.Seq[B]): LazyListIterable[A]^{this} = + if (knownIsEmpty) Empty + else super.intersect(that) + + @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]^{this}]^{this} = { + 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]^{this}]^{this} = { + 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]^{this}]^{this} = + if (knownIsEmpty) Iterator.empty + else + val it = new SlidingIterator[A](this, size = size, step = step) + it.asInstanceOf[Iterator[Nothing]] // CC cannot figure this out yet + + /** @inheritdoc + * + * $preservesLaziness + */ + override def padTo[B >: A](len: Int, elem: B): LazyListIterable[B]^{this} = + if (len <= 0) this + else newLL { + if (isEmpty) LazyListIterable.fill(len)(elem) + else eagerCons(head, tail.padTo(len - 1, elem)) + } + + /** @inheritdoc + * + * $preservesLaziness + */ + override 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) eagerHeadPrependIterator(other.iterator)(dropImpl(this, replaced)) + else if (isEmpty) eagerHeadFromIterator(other.iterator) + else eagerCons(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}]^{this} = super.transpose + + /** @inheritdoc + * + * $preservesLaziness + */ + override 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) eagerCons(elem, tail) + else if (tail.isEmpty) throw new IndexOutOfBoundsException(startIndex.toString) + else eagerCons(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): b.type = { + b.append(start) + if (!isEvaluated) b.append("") + else if (!isEmpty) { + b.append(head) + var cursor: LazyListIterable[A]^{this} = this + // explicit param to prevent an ObjectRef for cursor + @inline def appendHead(c: LazyListIterable[A]^): Unit = b.append(sep).append(c.head) + var scout: LazyListIterable[A]^{this} = tail + if (cursor ne scout) { + cursor = scout + if (scout.knownNonEmpty) { + scout = scout.tail + // Use 2x 1x iterator trick for cycle detection; slow iterator can add strings + while ((cursor ne scout) && scout.knownNonEmpty) { + appendHead(cursor) + cursor = cursor.tail + scout = scout.tail + if (scout.knownNonEmpty) scout = scout.tail + } + } + } + if (!scout.knownNonEmpty) { // Not a cycle, scout hit an end (empty or non-evaluated) + while (cursor ne scout) { + appendHead(cursor) + cursor = cursor.tail + } + // if cursor (eq scout) has state defined, it is empty; else unknown state + if (!cursor.isEvaluated) b.append(sep).append("") + } else { + // Cycle: the scout is `knownNonEmpty` and `eq cursor`. + // if the cycle starts at `this`, its elements were already added + if (cursor ne this) { + // 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: LazyListIterable[A]^{this} = this + while (runner ne scout) { + runner = runner.tail + scout = scout.tail + } + while({ + val ct = cursor.tail + if (ct ne scout) { + // In `lazy val xs: LazyListIterable[Int] = 1 #:: 2 #:: xs`, method `#::` creates a LazyListIterable instance which ends up as the 3rd element. + // That 3rd element initially has unknown head/tail. Once it completes, the tail is assigned to be `xs.tail`. + // So in memory the structure is `LLx(1, LLy(2, LLz(1, )))`. + // In `toString` we skip the last element to maintain the illusion. + appendHead(cursor) + } + cursor = ct + cursor ne scout + }) () + } + b.append(sep).append("") + } + } + b.append(end) + b + } + + /** $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 (!isEvaluated) false + else if (isEmpty) true + else { + // Two-iterator trick (2x & 1x speed) for cycle detection. + var those: LazyListIterable[A]^{this} = this + var these: LazyListIterable[A]^{this} = tail + while (those ne these) { + if (!these.isEvaluated) return false + else if (these.isEmpty) return true + these = these.tail + if (!these.isEvaluated) 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(4L) +object LazyListIterable extends IterableFactory[LazyListIterable] { + + // LazyListTest.countAlloc + // var k = 0 + // def kount(): Unit = k += 1 + + private object Uninitialized extends Serializable + private object MidEvaluation + private object EmptyMarker + + private val Empty: LazyListIterable[Nothing] = new LazyListIterable(EmptyMarker) + + /** Creates a new LazyListIterable. */ + @inline private def newLL[A](state: => LazyListIterable[A]^): LazyListIterable[A]^{state} = new LazyListIterable[A](() => state) + + /** Creates a new LazyListIterable with evaluated `head` and `tail`. */ + @inline private def eagerCons[A](hd: A, tl: LazyListIterable[A]^): LazyListIterable[A]^{tl} = new LazyListIterable[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 // val restRef = new ObjectRef(ll) + newLL { + var elem: A = null.asInstanceOf[A] + var found = false + var rest: LazyListIterable[A]^{ll} = 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) eagerCons(elem, filterImpl(rest, p, isFlipped)) else 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 // val restRef = new ObjectRef(ll) + 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: LazyListIterable[A]^{ll} = 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) Empty + else eagerCons(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 // val restRef = new ObjectRef(ll) + newLL { + var it: Iterator[B]^{f} = null + var itHasNext = false + var rest: LazyListIterable[A]^{ll} = 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 + eagerCons(head, newLL(eagerHeadPrependIterator(it)(flatMapImpl(rest, f)))) + } else 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 // val restRef = new ObjectRef(ll) + var iRef = n // val iRef = new IntRef(n) + newLL { + var rest: LazyListIterable[A]^{ll} = 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 + } + } + + 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 // val restRef = new ObjectRef(ll) + newLL { + var rest: LazyListIterable[A]^{ll} = restRef // var rest = restRef.elem + while (!rest.isEmpty && p(rest.head)) { + rest = rest.tail + restRef = rest // restRef.elem = rest + } + rest + } + } + + 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 // val restRef = new ObjectRef(ll) + var scoutRef: LazyListIterable[A]^{ll} = ll // val scoutRef = new ObjectRef(ll) + var remainingRef = n // val remainingRef = new IntRef(n) + newLL { + var scout: LazyListIterable[A]^{ll} = 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: LazyListIterable[A]^{ll} = 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 + } + } + + /** 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(eagerCons(hd, newLL(tl))) + + /** Maps a lazy list to its head and tail */ + def unapply[A](xs: LazyListIterable[A]^): Option[(A, LazyListIterable[A]^{xs})] = #::.unapply(xs) + } + + implicit def toDeferrer[A](l: => LazyListIterable[A]^): Deferrer[A]^{l} = new Deferrer[A](() => l) + + final class Deferrer[A] private[LazyListIterable] (private val l: () => LazyListIterable[A]^) extends AnyVal { self: Deferrer[A]^ => + /** Construct a LazyListIterable consisting of a given first element followed by elements + * from another LazyListIterable. + */ + def #:: [B >: A](elem: => B): LazyListIterable[B]^{this, elem} = newLL(eagerCons(elem, newLL(l()))) + /** Construct a LazyListIterable consisting of the concatenation of the given LazyListIterable and + * another LazyListIterable. + */ + def #:::[B >: A](prefix: LazyListIterable[B]^): LazyListIterable[B]^{this, prefix} = 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(eagerHeadFromIterator(coll.iterator)) + } + + def empty[A]: LazyListIterable[A] = Empty + + /** Creates a LazyListIterable with the elements of an iterator followed by a LazyListIterable suffix. + * Eagerly evaluates the first element. + */ + private def eagerHeadPrependIterator[A](it: Iterator[A]^)(suffix: => LazyListIterable[A]^): LazyListIterable[A]^{it, suffix} = + if (it.hasNext) eagerCons(it.next(), newLL(eagerHeadPrependIterator(it)(suffix))) + else suffix + + /** Creates a LazyListIterable from an Iterator. Eagerly evaluates the first element. */ + private def eagerHeadFromIterator[A](it: Iterator[A]^): LazyListIterable[A]^{it} = + if (it.hasNext) eagerCons(it.next(), newLL(eagerHeadFromIterator(it))) + else Empty + + override def concat[A](xss: collection.Iterable[A]*): LazyListIterable[A] = + if (xss.knownSize == 0) empty + else newLL(eagerHeadConcatIterators(xss.iterator)) + + private def eagerHeadConcatIterators[A](it: Iterator[collection.Iterable[A]^]^): LazyListIterable[A]^{it} = + if (!it.hasNext) Empty + else eagerHeadPrependIterator(it.next().iterator)(eagerHeadConcatIterators(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 + eagerCons(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(eagerCons(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(eagerCons(elem, continually(elem))) + + override def fill[A](n: Int)(elem: => A): LazyListIterable[A]^{elem} = + if (n > 0) newLL(eagerCons(elem, LazyListIterable.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(eagerCons(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)) => eagerCons(elem, unfold(state)(f)) + case None => Empty + } + } + + /** Unlike LazyList, the builder returned by this method will eagerly evaluate all elements + * passed to it in `addAll`. + * To create a LazyListIterable from an IterableOnce, use `fromSpecific`. + * + * @tparam A the type of the ${coll}’s elements + * @return A builder for $Coll objects. + */ + def newBuilder[A]: Builder[A, LazyListIterable[A]] = (new collection.mutable.ListBuffer[A]).mapResult(from) + + 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](l: LazyListIterable[A]^, size: Int, step: Int) + extends AbstractIterator[LazyListIterable[A]^{l}] { + private[this] var lazyList: LazyListIterable[A]^{l} = l + 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]^{l} = { + 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] { + 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) + } + + // CC Note: Lazy Builder is not unsafe, but requires an explicit capture set. + + // private final class LazyBuilder[A, Cap^] extends ReusableBuilder[A, LazyListIterable[A]] { + // import LazyBuilder._ + + // private[this] var next: DeferredState[A, Cap]^{Cap} = _ + // private[this] var list: LazyListIterable[A]^{Cap} = _ + + // clear() + + // override def clear(): Unit = { + // val deferred = new DeferredState[A, Cap] + // list = newLL(deferred.eval()) + // next = deferred + // } + + // override def result(): LazyListIterable[A]^{Cap} = { + // next init Empty + // list + // } + + // override def addOne(elem: A): this.type = { + // val deferred = new DeferredState[A, Cap] + // next init eagerCons(elem, newLL(deferred.eval())) + // next = deferred + // this + // } + + // // lazy implementation which doesn't evaluate the collection being added + // override def addAll(xs: IterableOnce[A]^{Cap}): this.type = { + // if (xs.knownSize != 0) { + // val deferred = new DeferredState[A, Cap] + // next init eagerHeadPrependIterator(xs.iterator)(deferred.eval()) + // next = deferred + // } + // this + // } + // } + + // private object LazyBuilder { + // final class DeferredState[A, Cap^] { + // private[this] var _tail: () ->{Cap} LazyListIterable[A]^{Cap} = _ + + // def eval(): LazyListIterable[A]^{Cap} = { + // val state = _tail + // if (state == null) throw new IllegalStateException("uninitialized") + // state() + // } + + // // racy + // def init(state: ->{Cap} LazyListIterable[A]^{Cap}): Unit = { + // if (_tail != null) throw new IllegalStateException("already initialized") + // _tail = () => state + // } + // } + // } + + /** This serialization proxy is used for LazyListIterables 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(4L) + final class SerializationProxy[A](of: LazyListIterable[A]^) extends Serializable { + @transient protected var coll: LazyListIterable[A]^{this} = of + + private[this] def writeObject(out: ObjectOutputStream): Unit = { + out.defaultWriteObject() + var these: LazyListIterable[A]^{this} = 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.evaluated` + // before the resulting LazyListIterable is returned + val it = init.toList.iterator + coll = newLL(eagerHeadPrependIterator(it)(tail)) + } + + private[this] def readResolve(): Any = coll + } +} diff --git a/library/src/scala/collection/immutable/List.scala b/library/src/scala/collection/immutable/List.scala index f7b828bb97b5..dde3e5e8a05c 100644 --- a/library/src/scala/collection/immutable/List.scala +++ b/library/src/scala/collection/immutable/List.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.unchecked.uncheckedVariance import scala.annotation.tailrec import mutable.{Builder, ListBuffer} @@ -144,7 +146,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 @@ -166,7 +168,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) } @@ -259,7 +261,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 @@ -287,7 +289,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 @@ -671,7 +673,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) @@ -686,7 +688,7 @@ 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() diff --git a/library/src/scala/collection/immutable/ListMap.scala b/library/src/scala/collection/immutable/ListMap.scala index 8b2cd61175fe..0d6ef12296e2 100644 --- a/library/src/scala/collection/immutable/ListMap.scala +++ b/library/src/scala/collection/immutable/ListMap.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{nowarn, tailrec} import scala.collection.mutable.ReusableBuilder import scala.collection.generic.DefaultSerializable @@ -241,7 +243,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] => @@ -324,7 +326,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/library/src/scala/collection/immutable/ListSet.scala b/library/src/scala/collection/immutable/ListSet.scala index 4325bd500b14..ed08c69d1b37 100644 --- a/library/src/scala/collection/immutable/ListSet.scala +++ b/library/src/scala/collection/immutable/ListSet.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec import scala.collection.generic.DefaultSerializable @@ -118,7 +120,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/library/src/scala/collection/immutable/LongMap.scala b/library/src/scala/collection/immutable/LongMap.scala index 9832b4a7d55c..fab52e1d1db2 100644 --- a/library/src/scala/collection/immutable/LongMap.scala +++ b/library/src/scala/collection/immutable/LongMap.scala @@ -14,6 +14,8 @@ package scala.collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import java.lang.IllegalStateException import scala.collection.generic.{BitOperations, DefaultSerializationProxy} @@ -53,7 +55,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]] = @@ -87,13 +89,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] } @@ -177,7 +179,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) @@ -477,12 +479,12 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] def map[V2](f: ((Long, T)) => (Long, V2)): LongMap[V2] = LongMap.from(new View.Map(coll, f)) - def flatMap[V2](f: ((Long, T)) => IterableOnce[(Long, V2)]): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) + 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/library/src/scala/collection/immutable/Map.scala b/library/src/scala/collection/immutable/Map.scala index b262243901c9..fc1f720c4865 100644 --- a/library/src/scala/collection/immutable/Map.scala +++ b/library/src/scala/collection/immutable/Map.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.unchecked.uncheckedVariance import scala.collection.generic.DefaultSerializable import scala.collection.immutable.Map.Map4 @@ -41,7 +43,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. @@ -62,7 +64,8 @@ trait Map[K, +V] */ transparent trait MapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C]] extends IterableOps[(K, V), Iterable, C] - with collection.MapOps[K, V, CC, C] { + with collection.MapOps[K, V, CC, C] + with caps.Pure { protected def coll: C with CC[K, V] @@ -88,10 +91,10 @@ transparent trait MapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapOps[ * @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 @@ -155,7 +158,7 @@ transparent trait StrictOptimizedMapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _] 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() @@ -173,7 +176,7 @@ transparent trait StrictOptimizedMapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _] 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 { @@ -189,7 +192,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) @@ -199,7 +202,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 = @@ -208,7 +211,7 @@ 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: 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, @@ -250,7 +253,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) } @@ -703,7 +706,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/library/src/scala/collection/immutable/NumericRange.scala b/library/src/scala/collection/immutable/NumericRange.scala index 6a10bef7171f..c09b49810b24 100644 --- a/library/src/scala/collection/immutable/NumericRange.scala +++ b/library/src/scala/collection/immutable/NumericRange.scala @@ -13,6 +13,8 @@ package scala.collection.immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.Stepper.EfficientSplit import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape} import scala.collection.generic.CommonErrors diff --git a/library/src/scala/collection/immutable/Queue.scala b/library/src/scala/collection/immutable/Queue.scala index 6deaabc5c7f7..326d3c7c56a6 100644 --- a/library/src/scala/collection/immutable/Queue.scala +++ b/library/src/scala/collection/immutable/Queue.scala @@ -14,6 +14,8 @@ package scala.collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.generic.DefaultSerializable import scala.collection.mutable.{Builder, ListBuffer} @@ -120,7 +122,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 @@ -151,7 +153,7 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L * @param iter an iterable object */ @deprecated("Use `enqueueAll` instead of `enqueue` to enqueue a collection of elements", "2.13.0") - @`inline` final def enqueue[B >: A](iter: scala.collection.Iterable[B]) = enqueueAll(iter) + @`inline` final def enqueue[B >: A](iter: scala.collection.Iterable[B]^) = enqueueAll(iter) /** Creates a new queue with all elements provided by an `Iterable` object * added at the end of the old queue. @@ -161,7 +163,7 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L * * @param iter an iterable object */ - def enqueueAll[B >: A](iter: scala.collection.Iterable[B]): Queue[B] = appendedAll(iter) + def enqueueAll[B >: A](iter: scala.collection.Iterable[B]^): Queue[B] = appendedAll(iter) /** Returns a tuple with the first element in the queue, * and a new queue with this element removed. @@ -203,7 +205,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/library/src/scala/collection/immutable/Range.scala b/library/src/scala/collection/immutable/Range.scala index 5fd0490596d7..1f361c70b7bb 100644 --- a/library/src/scala/collection/immutable/Range.scala +++ b/library/src/scala/collection/immutable/Range.scala @@ -14,6 +14,8 @@ package scala package collection.immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl.RangeStepper import scala.collection.generic.CommonErrors @@ -217,7 +219,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 +615,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 { self: Partial[T, U]^ => def by(x: T): U = f(x) override def toString = "Range requires step" } @@ -641,7 +643,7 @@ private class RangeIterator( step: Int, lastElement: Int, initiallyEmpty: Boolean -) extends AbstractIterator[Int] with Serializable { +) extends AbstractIterator[Int] with Serializable { self => private[this] var _hasNext: Boolean = !initiallyEmpty private[this] var _next: Int = start override def knownSize: Int = if (_hasNext) (lastElement - _next) / step + 1 else 0 diff --git a/library/src/scala/collection/immutable/RedBlackTree.scala b/library/src/scala/collection/immutable/RedBlackTree.scala index a57785bbf741..94d6ed434d75 100644 --- a/library/src/scala/collection/immutable/RedBlackTree.scala +++ b/library/src/scala/collection/immutable/RedBlackTree.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.meta.{getter, setter} import scala.annotation.tailrec import scala.runtime.Statics.releaseFence diff --git a/library/src/scala/collection/immutable/Seq.scala b/library/src/scala/collection/immutable/Seq.scala index fc11b697dc0c..cb6655c9b44c 100644 --- a/library/src/scala/collection/immutable/Seq.scala +++ b/library/src/scala/collection/immutable/Seq.scala @@ -15,6 +15,7 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking trait Seq[+A] extends Iterable[A] with collection.Seq[A] @@ -30,7 +31,7 @@ trait Seq[+A] extends Iterable[A] * @define coll immutable sequence * @define Coll `immutable.Seq` */ -transparent trait SeqOps[+A, +CC[_], +C] extends Any with collection.SeqOps[A, CC, C] +transparent trait SeqOps[+A, +CC[B] <: caps.Pure, +C] extends Any with collection.SeqOps[A, CC, C] with caps.Pure /** * $factoryInfo @@ -39,7 +40,7 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any with collection.SeqOps[A, 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) } @@ -59,7 +60,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 @@ -112,16 +113,17 @@ 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) } } /** Base trait for immutable indexed Seq operations */ -transparent trait IndexedSeqOps[+A, +CC[_], +C] +transparent trait IndexedSeqOps[+A, +CC[B] <: caps.Pure, +C] extends SeqOps[A, CC, C] - with collection.IndexedSeqOps[A, CC, C] { + with collection.IndexedSeqOps[A, CC, C] + with caps.Pure { override def slice(from: Int, until: Int): C = { // since we are immutable we can just share the same collection @@ -143,7 +145,7 @@ 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) } diff --git a/library/src/scala/collection/immutable/SeqMap.scala b/library/src/scala/collection/immutable/SeqMap.scala index 50a5dcfce382..fcc706deb792 100644 --- a/library/src/scala/collection/immutable/SeqMap.scala +++ b/library/src/scala/collection/immutable/SeqMap.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.mutable.{Builder, ReusableBuilder} /** A base trait for ordered, immutable maps. @@ -45,7 +47,7 @@ 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 @@ -274,7 +276,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/library/src/scala/collection/immutable/Set.scala b/library/src/scala/collection/immutable/Set.scala index 08fd4a13e9cd..c35189acbc0d 100644 --- a/library/src/scala/collection/immutable/Set.scala +++ b/library/src/scala/collection/immutable/Set.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.immutable.Set.Set4 import scala.collection.mutable.{Builder, ReusableBuilder} @@ -66,10 +68,10 @@ transparent trait SetOps[A, +CC[X], +C <: SetOps[A, CC, C]] * @param that the collection containing the elements to remove. * @return a new $coll with the given elements removed, omitting duplicates. */ - def removedAll(that: IterableOnce[A]): C = that.iterator.foldLeft[C](coll)(_ - _) + def removedAll(that: IterableOnce[A]^): C = that.iterator.foldLeft[C](coll)(_ - _) /** Alias for removedAll */ - override final def -- (that: IterableOnce[A]): C = removedAll(that) + override final def -- (that: IterableOnce[A]^): C = removedAll(that) } transparent trait StrictOptimizedSetOps[A, +CC[X], +C <: SetOps[A, CC, C]] @@ -77,7 +79,7 @@ transparent trait StrictOptimizedSetOps[A, +CC[X], +C <: SetOps[A, CC, C]] with collection.StrictOptimizedSetOps[A, CC, C] with StrictOptimizedIterableOps[A, CC, C] { - override def concat(that: collection.IterableOnce[A]): C = { + override def concat(that: collection.IterableOnce[A]^): C = { var result: C = coll val it = that.iterator while (it.hasNext) result = result + it.next() @@ -95,7 +97,7 @@ 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, @@ -124,7 +126,7 @@ object Set extends IterableFactory[Set] { override def knownSize: Int = size override def filter(pred: Any => Boolean): Set[Any] = this override def filterNot(pred: Any => Boolean): Set[Any] = this - override def removedAll(that: IterableOnce[Any]): Set[Any] = this + override def removedAll(that: IterableOnce[Any]^): Set[Any] = this override def diff(that: collection.Set[Any]): Set[Any] = this override def subsetOf(that: collection.Set[Any]): Boolean = true override def intersect(that: collection.Set[Any]): Set[Any] = this @@ -398,7 +400,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/library/src/scala/collection/immutable/SortedMap.scala b/library/src/scala/collection/immutable/SortedMap.scala index a25321235f89..b045c498d3c9 100644 --- a/library/src/scala/collection/immutable/SortedMap.scala +++ b/library/src/scala/collection/immutable/SortedMap.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.unchecked.uncheckedVariance import scala.collection.mutable.Builder @@ -70,7 +72,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. @@ -124,7 +126,7 @@ transparent trait StrictOptimizedSortedMapOps[K, +V, +CC[X, +Y] <: Map[X, Y] wit 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() @@ -135,12 +137,12 @@ transparent trait StrictOptimizedSortedMapOps[K, +V, +CC[X, +Y] <: Map[X, Y] wit @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 { @@ -162,14 +164,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/library/src/scala/collection/immutable/SortedSet.scala b/library/src/scala/collection/immutable/SortedSet.scala index e8bbf1810d48..ceeafeb6296b 100644 --- a/library/src/scala/collection/immutable/SortedSet.scala +++ b/library/src/scala/collection/immutable/SortedSet.scala @@ -15,6 +15,7 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking /** Base trait for sorted sets */ trait SortedSet[A] @@ -52,7 +53,7 @@ transparent trait StrictOptimizedSortedSetOps[A, +CC[X] <: SortedSet[X], +C <: S */ @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/library/src/scala/collection/immutable/Stream.scala b/library/src/scala/collection/immutable/Stream.scala index a7017a23a16d..b31c5c8018c6 100644 --- a/library/src/scala/collection/immutable/Stream.scala +++ b/library/src/scala/collection/immutable/Stream.scala @@ -25,7 +25,7 @@ import scala.collection.mutable.{ArrayBuffer, StringBuilder} import scala.language.implicitConversions import Stream.cons -@deprecated("Use LazyList (which is fully lazy) instead of Stream (which has a lazy tail only)", "2.13.0") +@deprecated("Use LazyListIterable (which is fully lazy) instead of Stream (which has a lazy tail only)", "2.13.0") @SerialVersionUID(3L) sealed abstract class Stream[+A] extends AbstractSeq[A] with LinearSeq[A] diff --git a/library/src/scala/collection/immutable/StrictOptimizedSeqOps.scala b/library/src/scala/collection/immutable/StrictOptimizedSeqOps.scala index 51be923eb719..c66c26ef1a05 100644 --- a/library/src/scala/collection/immutable/StrictOptimizedSeqOps.scala +++ b/library/src/scala/collection/immutable/StrictOptimizedSeqOps.scala @@ -15,17 +15,20 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.generic.CommonErrors /** Trait that overrides operations to take advantage of strict builders. */ -transparent trait StrictOptimizedSeqOps[+A, +CC[_], +C] +transparent trait StrictOptimizedSeqOps[+A, +CC[B] <: caps.Pure, +C] extends Any with SeqOps[A, CC, C] with collection.StrictOptimizedSeqOps[A, CC, C] - with StrictOptimizedIterableOps[A, CC, C] { + with StrictOptimizedIterableOps[A, CC, C] + with caps.Pure { - 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 @@ -62,7 +65,7 @@ transparent 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/library/src/scala/collection/immutable/TreeMap.scala b/library/src/scala/collection/immutable/TreeMap.scala index b4a7e4b6605d..84ca78c48b75 100644 --- a/library/src/scala/collection/immutable/TreeMap.scala +++ b/library/src/scala/collection/immutable/TreeMap.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.tailrec import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable @@ -149,7 +151,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) @@ -169,7 +171,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) @@ -310,7 +312,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 => @@ -354,7 +356,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/library/src/scala/collection/immutable/TreeSeqMap.scala b/library/src/scala/collection/immutable/TreeSeqMap.scala index e3a7552c5934..0741bcbaec58 100644 --- a/library/src/scala/collection/immutable/TreeSeqMap.scala +++ b/library/src/scala/collection/immutable/TreeSeqMap.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.tailrec /** This class implements an immutable map that preserves order using @@ -234,7 +236,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) { @@ -249,7 +251,7 @@ final class TreeSeqMap[K, +V] private ( bdr.result() } - override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]): TreeSeqMap[K2, V2] = { + override def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]^): TreeSeqMap[K2, V2] = { val bdr = newBuilder[K2, V2](orderedBy) val iter = ordering.iterator while (iter.hasNext) { @@ -260,7 +262,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) @@ -303,7 +305,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() diff --git a/library/src/scala/collection/immutable/TreeSet.scala b/library/src/scala/collection/immutable/TreeSet.scala index a9bf1979700a..d30380b88101 100644 --- a/library/src/scala/collection/immutable/TreeSet.scala +++ b/library/src/scala/collection/immutable/TreeSet.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.collection.mutable.ReusableBuilder @@ -171,7 +173,7 @@ final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[ def excl(elem: A): TreeSet[A] = newSetOrSelf(RB.delete(tree, elem)) - override def concat(that: collection.IterableOnce[A]): TreeSet[A] = { + override def concat(that: collection.IterableOnce[A]^): TreeSet[A] = { val t = that match { case ts: TreeSet[A] if ordering == ts.ordering => RB.union(tree, ts.tree) @@ -184,7 +186,7 @@ final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[ newSetOrSelf(t) } - override def removedAll(that: IterableOnce[A]): TreeSet[A] = that match { + override def removedAll(that: IterableOnce[A]^): TreeSet[A] = that match { case ts: TreeSet[A] if ordering == ts.ordering => newSetOrSelf(RB.difference(tree, ts.tree)) case _ => @@ -240,7 +242,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 => @@ -270,7 +272,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/library/src/scala/collection/immutable/Vector.scala b/library/src/scala/collection/immutable/Vector.scala index 4ea962fc8fa9..78768577b99b 100644 --- a/library/src/scala/collection/immutable/Vector.scala +++ b/library/src/scala/collection/immutable/Vector.scala @@ -14,6 +14,8 @@ package scala.collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import java.lang.Math.{abs, max => mmax, min => mmin} import java.util.Arrays.{copyOf, copyOfRange} import java.util.{Arrays, Spliterator} @@ -36,7 +38,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 _ => @@ -195,21 +197,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)*/) { @@ -227,7 +229,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) { @@ -373,10 +375,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 = @@ -427,13 +429,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) @@ -522,7 +524,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 => @@ -533,7 +535,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) @@ -644,7 +646,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 => @@ -656,7 +658,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) @@ -787,7 +789,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 => @@ -800,7 +802,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) @@ -951,7 +953,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 => @@ -965,7 +967,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) @@ -1136,7 +1138,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 => @@ -1151,7 +1153,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) @@ -1818,7 +1820,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]]) @@ -2187,7 +2189,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 { @@ -2212,7 +2214,7 @@ private object VectorStatics { } 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 { diff --git a/library/src/scala/collection/immutable/VectorMap.scala b/library/src/scala/collection/immutable/VectorMap.scala index 316d02037ec0..bf257fd7759e 100644 --- a/library/src/scala/collection/immutable/VectorMap.scala +++ b/library/src/scala/collection/immutable/VectorMap.scala @@ -15,6 +15,8 @@ package collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.annotation.{nowarn, tailrec} /** This class implements immutable maps using a vector/map-based data structure, which preserves insertion order. @@ -58,7 +60,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] = @@ -233,7 +235,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() diff --git a/library/src/scala/collection/immutable/WrappedString.scala b/library/src/scala/collection/immutable/WrappedString.scala index 76d69c092673..af2bdd6566e8 100644 --- a/library/src/scala/collection/immutable/WrappedString.scala +++ b/library/src/scala/collection/immutable/WrappedString.scala @@ -14,6 +14,8 @@ package scala.collection package immutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.Predef.{wrapString => _, assert} import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl.CharStringStepper @@ -35,11 +37,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 caps.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 @@ -66,13 +69,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) @@ -98,13 +101,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) } @@ -124,7 +127,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 b.sizeHint(it) b ++= it diff --git a/library/src/scala/collection/immutable/package.scala b/library/src/scala/collection/immutable/package.scala index 061619cb8b86..5ddc1810d701 100644 --- a/library/src/scala/collection/immutable/package.scala +++ b/library/src/scala/collection/immutable/package.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking package object immutable { type StringOps = scala.collection.StringOps diff --git a/library/src/scala/collection/mutable/AnyRefMap.scala b/library/src/scala/collection/mutable/AnyRefMap.scala index 3caccdbc194d..984fb1ff781e 100644 --- a/library/src/scala/collection/mutable/AnyRefMap.scala +++ b/library/src/scala/collection/mutable/AnyRefMap.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.meta.companionClass import scala.annotation.nowarn import scala.collection.generic.DefaultSerializationProxy @@ -44,7 +45,7 @@ import scala.language.implicitConversions * */ @(deprecated @companionClass)("Use `scala.collection.mutable.HashMap` instead for better performance.", since = "2.13.16") -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]] @@ -54,7 +55,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi def this() = this(AnyRefMap.exceptionDefault, 16, initBlank = true) /** Creates a new `AnyRefMap` that returns default values according to a supplied key-value mapping. */ - def this(defaultEntry: K => V) = this(defaultEntry, 16, initBlank = true) + def this(defaultEntry: K -> V) = this(defaultEntry, 16, initBlank = true) /** Creates a new `AnyRefMap` with an initial buffer of specified size. * @@ -64,7 +65,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi def this(initialBufferSize: Int) = this(AnyRefMap.exceptionDefault, initialBufferSize, initBlank = true) /** Creates a new `AnyRefMap` with specified default values and initial buffer size. */ - def this(defaultEntry: K => V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, initBlank = true) + def this(defaultEntry: K -> V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, initBlank = true) private[this] var mask = 0 private[this] var _size = 0 @@ -90,7 +91,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) @@ -403,18 +404,19 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi override def + [V1 >: V](kv: (K, V1)): AnyRefMap[K, V1] = AnyRefMap.from(new View.Appended(this, kv)) @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") - override def + [V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): AnyRefMap[K, V1] = { + override def + [V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): AnyRefMap[K, V1]^{} = { + // An empty capture annotation is needed in the result type to satisfy the overriding checker. val m = this + elem1 + elem2 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] = @@ -498,7 +500,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi * @param f the mapping function must produce key-value pairs where the key is an `AnyRef` * @param dummy an implicit placeholder for purposes of distinguishing the (erased) signature of this method */ - def flatMap[K2 <: AnyRef, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def flatMap[K2 <: AnyRef, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^)(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.FlatMap(this, f)) /** * An overload of `collect` which produces an `AnyRefMap`. @@ -556,7 +558,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) @@ -569,7 +571,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. @@ -579,7 +581,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) } @@ -613,13 +615,13 @@ 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 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] } diff --git a/library/src/scala/collection/mutable/ArrayBuffer.scala b/library/src/scala/collection/mutable/ArrayBuffer.scala index 72384e3f65a2..b8fa9c806e5e 100644 --- a/library/src/scala/collection/mutable/ArrayBuffer.scala +++ b/library/src/scala/collection/mutable/ArrayBuffer.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import java.util.Arrays import scala.annotation.{nowarn, tailrec} import scala.collection.Stepper.EfficientSplit @@ -147,7 +148,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 @@ -176,7 +177,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] => @@ -230,7 +231,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" @@ -294,7 +295,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 @@ -372,10 +373,11 @@ final class ArrayBufferView[A] private[mutable](underlying: ArrayBuffer[A], muta this({ val _array = array val _length = length - new ArrayBuffer[A](0) { + val buf = new ArrayBuffer[A](0) { this.array = _array this.size0 = _length } + buf }, () => 0) } @@ -388,21 +390,21 @@ final class ArrayBufferView[A] private[mutable](underlying: ArrayBuffer[A], muta override protected[this] def className = "ArrayBufferView" // we could inherit all these from `CheckedIndexedSeqView`, except this class is public - 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]^{suffix, this} = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) + override def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]^): IndexedSeqView[B]^{suffix, this} = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) + override def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]^): IndexedSeqView[B]^{prefix, this} = new CheckedIndexedSeqView.Concat(prefix, this)(mutationCount) } diff --git a/library/src/scala/collection/mutable/ArrayBuilder.scala b/library/src/scala/collection/mutable/ArrayBuilder.scala index c6bd34a4001c..608fb85564a3 100644 --- a/library/src/scala/collection/mutable/ArrayBuilder.scala +++ b/library/src/scala/collection/mutable/ArrayBuilder.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.mutable.ArrayBuffer.resizeUp import scala.reflect.ClassTag @@ -66,7 +67,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) @@ -452,6 +453,7 @@ object ArrayBuilder { /** A class for array builders for arrays of `boolean`s. It can be reused. */ @SerialVersionUID(3L) class ofBoolean extends ArrayBuilder[Boolean] { + this: ofBoolean^{} => protected var elems: Array[Boolean] = _ @@ -504,7 +506,7 @@ object ArrayBuilder { this } - override def addAll(xs: IterableOnce[Unit]): this.type = { + override def addAll(xs: IterableOnce[Unit]^): this.type = { val newSize = size + xs.iterator.size ensureSize(newSize) size = newSize diff --git a/library/src/scala/collection/mutable/ArrayDeque.scala b/library/src/scala/collection/mutable/ArrayDeque.scala index 186df5b21c74..e395a651778c 100644 --- a/library/src/scala/collection/mutable/ArrayDeque.scala +++ b/library/src/scala/collection/mutable/ArrayDeque.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.nowarn import scala.collection.Stepper.EfficientSplit import scala.collection.generic.{CommonErrors, DefaultSerializable} @@ -100,7 +101,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 @@ -132,7 +133,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) @@ -178,7 +179,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) { @@ -528,7 +529,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) @@ -569,7 +570,7 @@ object ArrayDeque extends StrictOptimizedSeqFactory[ArrayDeque] { } } -transparent trait ArrayDequeOps[A, +CC[_], +C <: AnyRef] extends StrictOptimizedSeqOps[A, CC, C] { +transparent trait ArrayDequeOps[A, +CC[_] <: caps.Pure, +C <: AnyRef] extends StrictOptimizedSeqOps[A, CC, C] { protected def array: Array[AnyRef] final override def clone(): C = klone() diff --git a/library/src/scala/collection/mutable/ArraySeq.scala b/library/src/scala/collection/mutable/ArraySeq.scala index a6af2be04fff..53afc6cf66be 100644 --- a/library/src/scala/collection/mutable/ArraySeq.scala +++ b/library/src/scala/collection/mutable/ArraySeq.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import java.util.Arrays import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl._ @@ -43,7 +44,7 @@ sealed abstract class ArraySeq[T] 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(using elemTag).asInstanceOf[ArrayBuilder[T]] b.sizeHint(coll, delta = 0) b ++= coll @@ -106,7 +107,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) diff --git a/library/src/scala/collection/mutable/BitSet.scala b/library/src/scala/collection/mutable/BitSet.scala index 39124537758f..03f81bf64907 100644 --- a/library/src/scala/collection/mutable/BitSet.scala +++ b/library/src/scala/collection/mutable/BitSet.scala @@ -15,6 +15,8 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking + import scala.collection.immutable.Range import BitSetOps.{LogWL, MaxSize} import scala.annotation.implicitNotFound @@ -48,7 +50,7 @@ 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 @@ -176,19 +178,19 @@ class BitSet(protected[collection] final var elems: Array[Long]) override def map[B](f: Int => B)(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = super[StrictOptimizedSortedSetOps].map(f) - override def flatMap(f: Int => IterableOnce[Int]): BitSet = strictOptimizedFlatMap(newSpecificBuilder, f) - override def flatMap[B](f: Int => IterableOnce[B])(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = + override def flatMap(f: Int => IterableOnce[Int]^): BitSet = strictOptimizedFlatMap(newSpecificBuilder, f) + override def flatMap[B](f: Int => IterableOnce[B]^)(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = super[StrictOptimizedSortedSetOps].flatMap(f) - override def collect(pf: PartialFunction[Int, Int]): BitSet = strictOptimizedCollect(newSpecificBuilder, pf) - override def collect[B](pf: scala.PartialFunction[Int, B])(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = + override def collect(pf: PartialFunction[Int, Int]^): BitSet = strictOptimizedCollect(newSpecificBuilder, pf) + override def collect[B](pf: scala.PartialFunction[Int, B]^)(implicit @implicitNotFound(collection.BitSet.ordMsg) ev: Ordering[B]): SortedSet[B] = super[StrictOptimizedSortedSetOps].collect(pf) // necessary for disambiguation - override def zip[B](that: IterableOnce[B])(implicit @implicitNotFound(collection.BitSet.zipOrdMsg) ev: Ordering[(Int, B)]): SortedSet[(Int, B)] = + 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 => @@ -261,7 +263,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) } @@ -361,7 +363,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/library/src/scala/collection/mutable/Buffer.scala b/library/src/scala/collection/mutable/Buffer.scala index 333d86fce772..bfed8dd0add4 100644 --- a/library/src/scala/collection/mutable/Buffer.scala +++ b/library/src/scala/collection/mutable/Buffer.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.nowarn @@ -27,7 +28,7 @@ trait Buffer[A] with SeqOps[A, Buffer, Buffer[A]] with Growable[A] with Shrinkable[A] - with IterableFactoryDefaults[A, Buffer] { + with IterableFactoryDefaults[A, Buffer] { self => override def iterableFactory: SeqFactory[Buffer] = Buffer @@ -55,7 +56,7 @@ trait Buffer[A] * @param elems the iterable object containing the elements to append. * @return this $coll */ - @`inline` final def appendAll(@deprecatedName("xs") elems: IterableOnce[A]): this.type = addAll(elems) + @`inline` final def appendAll(@deprecatedName("xs") elems: IterableOnce[A]^): this.type = addAll(elems) /** Alias for `prepend` */ @`inline` final def +=: (elem: A): this.type = prepend(elem) @@ -64,13 +65,13 @@ trait Buffer[A] * @param elems the iterable object containing the elements to append. * @return this $coll */ - 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. * @@ -91,7 +92,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. * @@ -153,7 +154,7 @@ trait Buffer[A] * @param replaced the number of elements to drop in the original $coll * @return this $coll */ - 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: @@ -262,11 +263,11 @@ trait IndexedBuffer[A] extends IndexedSeq[A] * @param f the mapping function * @return this $coll */ - 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 @@ -294,7 +295,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/library/src/scala/collection/mutable/Builder.scala b/library/src/scala/collection/mutable/Builder.scala index c545929fa33f..715ae02bc519 100644 --- a/library/src/scala/collection/mutable/Builder.scala +++ b/library/src/scala/collection/mutable/Builder.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking /** Base trait for collection builders. * @@ -22,7 +23,7 @@ import scala.language.`2.13` * * @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. @@ -67,7 +68,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 (zero if omitted). */ - final def sizeHint(coll: scala.collection.IterableOnce[_], delta: Int = 0): Unit = + final def sizeHint(coll: scala.collection.IterableOnce[_]^, delta: Int = 0): Unit = coll.knownSize match { case -1 => case sz => sizeHint(0 max sz + delta) @@ -86,7 +87,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)) @@ -94,10 +95,10 @@ trait Builder[-A, +To] extends Growable[A] { self => } /** A builder resulting from this builder by 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/library/src/scala/collection/mutable/CheckedIndexedSeqView.scala b/library/src/scala/collection/mutable/CheckedIndexedSeqView.scala index 720e8ce90b95..2c9d002ac88e 100644 --- a/library/src/scala/collection/mutable/CheckedIndexedSeqView.scala +++ b/library/src/scala/collection/mutable/CheckedIndexedSeqView.scala @@ -15,34 +15,35 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking private[mutable] trait CheckedIndexedSeqView[+A] extends IndexedSeqView[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, suffix} = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) + override def appendedAll[B >: A](suffix: IndexedSeqView.SomeIndexedSeqOps[B]^): IndexedSeqView[B]^{this, suffix} = new CheckedIndexedSeqView.Concat(this, suffix)(mutationCount) + override def prependedAll[B >: A](prefix: IndexedSeqView.SomeIndexedSeqOps[B]^): IndexedSeqView[B]^{this, prefix} = 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 = { @@ -52,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 = { @@ -62,52 +63,52 @@ 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 { + override def reverse: IndexedSeqView[A]^{this} = underlying match { case x: IndexedSeqView[A] => x case _ => super.reverse } } @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/library/src/scala/collection/mutable/Cloneable.scala b/library/src/scala/collection/mutable/Cloneable.scala index 7480b5bae613..b84c5b225bb1 100644 --- a/library/src/scala/collection/mutable/Cloneable.scala +++ b/library/src/scala/collection/mutable/Cloneable.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking /** A trait for cloneable collections. * diff --git a/library/src/scala/collection/mutable/CollisionProofHashMap.scala b/library/src/scala/collection/mutable/CollisionProofHashMap.scala index 18d469c42900..35fa6393deab 100644 --- a/library/src/scala/collection/mutable/CollisionProofHashMap.scala +++ b/library/src/scala/collection/mutable/CollisionProofHashMap.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.{unchecked => uc} import scala.annotation.{implicitNotFound, tailrec, unused} import scala.annotation.unchecked.uncheckedVariance @@ -64,7 +65,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] @@ -174,7 +175,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 = { sizeHint(xs, delta = contentSize) super.addAll(xs) } @@ -426,7 +427,7 @@ final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double * @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)]) + def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^) (implicit @implicitNotFound(CollisionProofHashMap.ordMsg) ordering: Ordering[K2]): CollisionProofHashMap[K2, V2] = sortedMapFactory.from(new View.FlatMap(this, f)) @@ -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)(using ordering) } diff --git a/library/src/scala/collection/mutable/Growable.scala b/library/src/scala/collection/mutable/Growable.scala index 9caed94240e2..1ce3b3b0d99e 100644 --- a/library/src/scala/collection/mutable/Growable.scala +++ b/library/src/scala/collection/mutable/Growable.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +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 @@ -56,7 +57,7 @@ trait Growable[-A] extends Clearable { * @param elems the IterableOnce producing the elements to $add. * @return the $coll itself. */ - def addAll(@deprecatedName("xs") elems: IterableOnce[A]): this.type = { + def addAll(@deprecatedName("xs") elems: IterableOnce[A]^): this.type = { if (elems.asInstanceOf[AnyRef] eq this) addAll(Buffer.from(elems)) // avoid mutating under our own iterator else { val it = elems.iterator @@ -68,7 +69,7 @@ trait Growable[-A] extends Clearable { } /** Alias for `addAll` */ - @inline final def ++= (@deprecatedName("xs") elems: IterableOnce[A]): this.type = addAll(elems) + @inline final def ++= (@deprecatedName("xs") elems: IterableOnce[A]^): this.type = addAll(elems) /** The number of elements in the collection under construction, if it can be cheaply computed, -1 otherwise. * @@ -86,7 +87,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/library/src/scala/collection/mutable/GrowableBuilder.scala b/library/src/scala/collection/mutable/GrowableBuilder.scala index e98aa16c2581..cb18a6838b0f 100644 --- a/library/src/scala/collection/mutable/GrowableBuilder.scala +++ b/library/src/scala/collection/mutable/GrowableBuilder.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.language.`2.13` +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. @@ -32,7 +33,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/library/src/scala/collection/mutable/HashMap.scala b/library/src/scala/collection/mutable/HashMap.scala index 7980ffe08bd7..3204d0924110 100644 --- a/library/src/scala/collection/mutable/HashMap.scala +++ b/library/src/scala/collection/mutable/HashMap.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.{nowarn, tailrec} import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializationProxy @@ -95,7 +96,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) xs match { @@ -183,7 +184,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 } @@ -599,7 +600,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) @@ -620,7 +621,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/library/src/scala/collection/mutable/HashSet.scala b/library/src/scala/collection/mutable/HashSet.scala index df0cb0a9ee33..a92db177c110 100644 --- a/library/src/scala/collection/mutable/HashSet.scala +++ b/library/src/scala/collection/mutable/HashSet.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.tailrec import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializationProxy @@ -91,7 +92,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, delta = 0) xs match { case hs: immutable.HashSet[A] => @@ -115,7 +116,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 } @@ -407,7 +408,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 @@ -430,7 +431,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/library/src/scala/collection/mutable/HashTable.scala b/library/src/scala/collection/mutable/HashTable.scala index 08bdd68eece3..738adce7dfaa 100644 --- a/library/src/scala/collection/mutable/HashTable.scala +++ b/library/src/scala/collection/mutable/HashTable.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import collection.{AbstractIterator, Iterator} import java.lang.Integer.{numberOfLeadingZeros, rotateRight} diff --git a/library/src/scala/collection/mutable/ImmutableBuilder.scala b/library/src/scala/collection/mutable/ImmutableBuilder.scala index 6806367e53a4..5c263dab8ed7 100644 --- a/library/src/scala/collection/mutable/ImmutableBuilder.scala +++ b/library/src/scala/collection/mutable/ImmutableBuilder.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking /** * Reusable builder for immutable collections diff --git a/library/src/scala/collection/mutable/IndexedSeq.scala b/library/src/scala/collection/mutable/IndexedSeq.scala index 31feb34395f8..0f2c7b457613 100644 --- a/library/src/scala/collection/mutable/IndexedSeq.scala +++ b/library/src/scala/collection/mutable/IndexedSeq.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking trait IndexedSeq[T] extends Seq[T] with scala.collection.IndexedSeq[T] @@ -26,9 +27,10 @@ trait IndexedSeq[T] extends Seq[T] @SerialVersionUID(3L) object IndexedSeq extends SeqFactory.Delegate[IndexedSeq](ArrayBuffer) -transparent trait IndexedSeqOps[A, +CC[_], +C <: AnyRef] +transparent trait IndexedSeqOps[A, +CC[_] <: caps.Pure, +C <: AnyRef] extends scala.collection.IndexedSeqOps[A, CC, C] - with SeqOps[A, CC, C] { + with SeqOps[A, CC, C] + with caps.Pure { /** Modifies this $coll by applying a function to all elements of this $coll. * diff --git a/library/src/scala/collection/mutable/Iterable.scala b/library/src/scala/collection/mutable/Iterable.scala index 7f018b00c17f..14de48a768b5 100644 --- a/library/src/scala/collection/mutable/Iterable.scala +++ b/library/src/scala/collection/mutable/Iterable.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.{IterableFactory, IterableFactoryDefaults} trait Iterable[A] diff --git a/library/src/scala/collection/mutable/LinkedHashMap.scala b/library/src/scala/collection/mutable/LinkedHashMap.scala index 5a4f9285972d..a2b1b0e8f94b 100644 --- a/library/src/scala/collection/mutable/LinkedHashMap.scala +++ b/library/src/scala/collection/mutable/LinkedHashMap.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.{nowarn, tailrec} import scala.collection.generic.DefaultSerializable import scala.util.hashing.MurmurHash3 @@ -479,7 +480,7 @@ 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, delta = 0) newlhm.addAll(it) diff --git a/library/src/scala/collection/mutable/LinkedHashSet.scala b/library/src/scala/collection/mutable/LinkedHashSet.scala index 79d3d62a41d1..f0c2d2d843c3 100644 --- a/library/src/scala/collection/mutable/LinkedHashSet.scala +++ b/library/src/scala/collection/mutable/LinkedHashSet.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.{nowarn, tailrec} import scala.collection.generic.DefaultSerializable import scala.util.hashing.MurmurHash3 @@ -317,7 +318,7 @@ 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, delta = 0) newlhs.addAll(it) diff --git a/library/src/scala/collection/mutable/ListBuffer.scala b/library/src/scala/collection/mutable/ListBuffer.scala index e5858f79eb5e..f90423b40f67 100644 --- a/library/src/scala/collection/mutable/ListBuffer.scala +++ b/library/src/scala/collection/mutable/ListBuffer.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.{nowarn, tailrec} import scala.collection.generic.CommonErrors import scala.collection.immutable.{::, List, Nil} @@ -123,7 +124,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 @@ -142,7 +143,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) @@ -251,7 +252,7 @@ class ListBuffer[A] } } - def insertAll(idx: Int, elems: IterableOnce[A]): Unit = { + def insertAll(idx: Int, elems: IterableOnce[A]^): Unit = { if (idx < 0 || idx > len) throw CommonErrors.indexOutOfBounds(index = idx, max = len - 1) val it = elems.iterator if (it.hasNext) { @@ -318,7 +319,7 @@ class ListBuffer[A] * @param f the mapping function * @return this $coll */ - 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 @@ -363,7 +364,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 @@ -413,7 +414,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/library/src/scala/collection/mutable/ListMap.scala b/library/src/scala/collection/mutable/ListMap.scala index 3bb7e9bd54bb..ce66f09b0233 100644 --- a/library/src/scala/collection/mutable/ListMap.scala +++ b/library/src/scala/collection/mutable/ListMap.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.tailrec import scala.collection.generic.DefaultSerializable import scala.collection.immutable.List @@ -78,6 +79,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/library/src/scala/collection/mutable/LongMap.scala b/library/src/scala/collection/mutable/LongMap.scala index a56d874a5fc2..fe9dab81dc24 100644 --- a/library/src/scala/collection/mutable/LongMap.scala +++ b/library/src/scala/collection/mutable/LongMap.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.generic.DefaultSerializationProxy import scala.language.implicitConversions @@ -37,7 +38,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]] @@ -47,7 +48,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff def this() = this(LongMap.exceptionDefault, 16, initBlank = 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) @@ -57,7 +58,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, initBlank = true) + def this(defaultEntry: Long -> V) = this(defaultEntry, 16, initBlank = true) /** Creates a new `LongMap` with an initial buffer of specified size. * @@ -67,7 +68,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff def this(initialBufferSize: Int) = this(LongMap.exceptionDefault, initialBufferSize, initBlank = true) /** Creates a new `LongMap` with specified default values and initial buffer size. */ - def this(defaultEntry: Long => V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, initBlank = true) + def this(defaultEntry: Long -> V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, initBlank = true) private[this] var mask = 0 private[this] var extraKeys: Int = 0 @@ -468,18 +469,19 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff } @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") - override def + [V1 >: V](elem1: (Long, V1), elem2: (Long, V1), elems: (Long, V1)*): LongMap[V1] = { + override def + [V1 >: V](elem1: (Long, V1), elem2: (Long, V1), elems: (Long, V1)*): LongMap[V1]^{} = { + // TODO: An empty capture annotation is needed in the result type to satisfy the overriding checker. val m = this + elem1 + elem2 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] = @@ -572,7 +574,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff * * @param f the mapping function */ - def flatMap[V2](f: ((Long, V)) => IterableOnce[(Long, V2)]): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) + def flatMap[V2](f: ((Long, V)) => IterableOnce[(Long, V2)]^): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) /** An overload of `collect` which produces a `LongMap`. * @@ -612,7 +614,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) @@ -625,7 +627,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. @@ -634,7 +636,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) } @@ -670,13 +672,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 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): ReusableBuilder[(Long, AnyRef), LongMap[AnyRef]] = LongMap.newBuilder[AnyRef] } diff --git a/library/src/scala/collection/mutable/Map.scala b/library/src/scala/collection/mutable/Map.scala index df6f036b62d9..9e87fb25e88f 100644 --- a/library/src/scala/collection/mutable/Map.scala +++ b/library/src/scala/collection/mutable/Map.scala @@ -14,6 +14,8 @@ package scala package collection package mutable +import language.experimental.captureChecking + import scala.language.`2.13` /** Base type of mutable Maps */ @@ -46,7 +48,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. @@ -70,7 +72,8 @@ transparent trait MapOps[K, V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, with Cloneable[C] with Builder[(K, V), C] with Growable[(K, V)] - with Shrinkable[K] { + with Shrinkable[K] + with caps.Pure { def result(): C = coll @@ -233,7 +236,7 @@ transparent trait MapOps[K, V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, 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 { @@ -252,12 +255,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/library/src/scala/collection/mutable/MultiMap.scala b/library/src/scala/collection/mutable/MultiMap.scala index f96a2ca94754..a92f5a8f5712 100644 --- a/library/src/scala/collection/mutable/MultiMap.scala +++ b/library/src/scala/collection/mutable/MultiMap.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking /** A trait for mutable maps with multiple values assigned to a key. * diff --git a/library/src/scala/collection/mutable/MutationTracker.scala b/library/src/scala/collection/mutable/MutationTracker.scala index 6b41ac22db37..ddd3a912a840 100644 --- a/library/src/scala/collection/mutable/MutationTracker.scala +++ b/library/src/scala/collection/mutable/MutationTracker.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import java.util.ConcurrentModificationException /** diff --git a/library/src/scala/collection/mutable/OpenHashMap.scala b/library/src/scala/collection/mutable/OpenHashMap.scala index 36d77098512b..66a82fe50704 100644 --- a/library/src/scala/collection/mutable/OpenHashMap.scala +++ b/library/src/scala/collection/mutable/OpenHashMap.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import java.lang.Integer.numberOfLeadingZeros import java.util.ConcurrentModificationException import scala.collection.generic.DefaultSerializable @@ -27,7 +28,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/library/src/scala/collection/mutable/PriorityQueue.scala b/library/src/scala/collection/mutable/PriorityQueue.scala index f0146450e50f..050fa5159ee6 100644 --- a/library/src/scala/collection/mutable/PriorityQueue.scala +++ b/library/src/scala/collection/mutable/PriorityQueue.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.generic.DefaultSerializationProxy import scala.math.Ordering @@ -112,7 +113,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) 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 @@ -172,7 +173,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) @@ -238,7 +239,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) * @param xs a iterable object. * @return a new priority queue containing elements of both `xs` and `this`. */ - def ++(xs: IterableOnce[A]): PriorityQueue[A] = { this.clone() ++= xs } + def ++(xs: IterableOnce[A]^): PriorityQueue[A] = { this.clone() ++= xs } /** Adds all elements to the queue. * @@ -406,7 +407,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/library/src/scala/collection/mutable/Queue.scala b/library/src/scala/collection/mutable/Queue.scala index 7a0c25c049b6..91c2fdd81334 100644 --- a/library/src/scala/collection/mutable/Queue.scala +++ b/library/src/scala/collection/mutable/Queue.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.nowarn import scala.collection.generic.DefaultSerializable @@ -67,7 +68,7 @@ class Queue[A] protected (array: Array[AnyRef], start: Int, end: Int) * @param elems the iterable object. * @return this */ - def enqueueAll(elems: scala.collection.IterableOnce[A]): this.type = this ++= elems + def enqueueAll(elems: scala.collection.IterableOnce[A]^): this.type = this ++= elems /** * Removes the first element from this queue and returns it @@ -130,7 +131,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/library/src/scala/collection/mutable/RedBlackTree.scala b/library/src/scala/collection/mutable/RedBlackTree.scala index e4f2c54017a8..7a64730d7449 100644 --- a/library/src/scala/collection/mutable/RedBlackTree.scala +++ b/library/src/scala/collection/mutable/RedBlackTree.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.tailrec import collection.{AbstractIterator, Iterator} import java.lang.String diff --git a/library/src/scala/collection/mutable/ReusableBuilder.scala b/library/src/scala/collection/mutable/ReusableBuilder.scala index 1cba786c749a..0523c2c3066e 100644 --- a/library/src/scala/collection/mutable/ReusableBuilder.scala +++ b/library/src/scala/collection/mutable/ReusableBuilder.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +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/library/src/scala/collection/mutable/Seq.scala b/library/src/scala/collection/mutable/Seq.scala index ed5416ab7fe6..3f8047774adb 100644 --- a/library/src/scala/collection/mutable/Seq.scala +++ b/library/src/scala/collection/mutable/Seq.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.{IterableFactoryDefaults, SeqFactory} trait Seq[A] @@ -36,9 +37,10 @@ object Seq extends SeqFactory.Delegate[Seq](ArrayBuffer) * @define coll mutable sequence * @define Coll `mutable.Seq` */ -transparent trait SeqOps[A, +CC[_], +C <: AnyRef] +transparent trait SeqOps[A, +CC[_] <: caps.Pure, +C <: AnyRef] extends collection.SeqOps[A, CC, C] - with Cloneable[C] { + with Cloneable[C] + with caps.Pure { override def clone(): C = { val b = newSpecificBuilder diff --git a/library/src/scala/collection/mutable/SeqMap.scala b/library/src/scala/collection/mutable/SeqMap.scala index bad3ea10b243..4e6383e4b43a 100644 --- a/library/src/scala/collection/mutable/SeqMap.scala +++ b/library/src/scala/collection/mutable/SeqMap.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking /** * A generic trait for ordered mutable maps. Concrete classes have to provide diff --git a/library/src/scala/collection/mutable/Set.scala b/library/src/scala/collection/mutable/Set.scala index 299cab4ac23c..808132ea2dbc 100644 --- a/library/src/scala/collection/mutable/Set.scala +++ b/library/src/scala/collection/mutable/Set.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.{IterableFactory, IterableFactoryDefaults, IterableOps} /** Base trait for mutable sets */ diff --git a/library/src/scala/collection/mutable/Shrinkable.scala b/library/src/scala/collection/mutable/Shrinkable.scala index 96171c6df024..587530dba044 100644 --- a/library/src/scala/collection/mutable/Shrinkable.scala +++ b/library/src/scala/collection/mutable/Shrinkable.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.tailrec /** This trait forms part of collections that can be reduced @@ -53,7 +54,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) @@ -75,6 +76,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/library/src/scala/collection/mutable/SortedMap.scala b/library/src/scala/collection/mutable/SortedMap.scala index 534149aaf053..c16a01384785 100644 --- a/library/src/scala/collection/mutable/SortedMap.scala +++ b/library/src/scala/collection/mutable/SortedMap.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.{SortedMapFactory, SortedMapFactoryDefaults} /** @@ -38,7 +39,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. @@ -67,7 +68,7 @@ transparent trait SortedMapOps[K, V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, 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]] @@ -92,10 +93,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/library/src/scala/collection/mutable/SortedSet.scala b/library/src/scala/collection/mutable/SortedSet.scala index dbb31ba5a18d..e56fdc2859f6 100644 --- a/library/src/scala/collection/mutable/SortedSet.scala +++ b/library/src/scala/collection/mutable/SortedSet.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking /** Base type for mutable sorted set collections */ diff --git a/library/src/scala/collection/mutable/Stack.scala b/library/src/scala/collection/mutable/Stack.scala index f888475c7544..8ca4b58a7af6 100644 --- a/library/src/scala/collection/mutable/Stack.scala +++ b/library/src/scala/collection/mutable/Stack.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.{migration, nowarn} import scala.collection.generic.DefaultSerializable import scala.collection.{IterableFactoryDefaults, IterableOnce, SeqFactory, StrictOptimizedSeqFactory, StrictOptimizedSeqOps} @@ -77,7 +78,7 @@ class Stack[A] protected (array: Array[AnyRef], start: Int, end: Int) * @param elems the iterable object. * @return the stack with the new elements on top. */ - def pushAll(elems: scala.collection.IterableOnce[A]): this.type = + def pushAll(elems: scala.collection.IterableOnce[A]^): this.type = prependAll(elems match { case it: scala.collection.Seq[A] => it.view.reverse case it => IndexedSeq.from(it).view.reverse @@ -134,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/library/src/scala/collection/mutable/StringBuilder.scala b/library/src/scala/collection/mutable/StringBuilder.scala index dfd778b44b34..91baa747f219 100644 --- a/library/src/scala/collection/mutable/StringBuilder.scala +++ b/library/src/scala/collection/mutable/StringBuilder.scala @@ -13,6 +13,7 @@ package scala.collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.{IterableFactoryDefaults, IterableOnce} import scala.collection.immutable.WrappedString @@ -82,7 +83,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] = @@ -185,7 +186,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 @@ -314,7 +315,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/library/src/scala/collection/mutable/TreeMap.scala b/library/src/scala/collection/mutable/TreeMap.scala index 85b8d897f22a..04bd71a424d6 100644 --- a/library/src/scala/collection/mutable/TreeMap.scala +++ b/library/src/scala/collection/mutable/TreeMap.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.collection.mutable.{RedBlackTree => RB} @@ -200,7 +201,7 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: override def get(key: K) = if (isInsideViewBounds(key)) RB.get(tree, key) else None - override def iterator = if (RB.size(tree) == 0) Iterator.empty else RB.iterator(tree, from, until) + override def iterator: Iterator[(K, V)] = if (RB.size(tree) == 0) Iterator.empty else RB.iterator(tree, from, until) override def keysIterator: Iterator[K] = if (RB.size(tree) == 0) Iterator.empty else RB.keysIterator(tree, from, until) override def valuesIterator: Iterator[V] = if (RB.size(tree) == 0) Iterator.empty else RB.valuesIterator(tree, from, until) override def keysIteratorFrom(start: K) = if (RB.size(tree) == 0) Iterator.empty else RB.keysIterator(tree, pickLowerBound(Some(start)), until) @@ -248,7 +249,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/library/src/scala/collection/mutable/TreeSet.scala b/library/src/scala/collection/mutable/TreeSet.scala index 4f302d46906e..f54423cbe12d 100644 --- a/library/src/scala/collection/mutable/TreeSet.scala +++ b/library/src/scala/collection/mutable/TreeSet.scala @@ -14,6 +14,7 @@ package scala package collection.mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.collection.mutable.{RedBlackTree => RB} @@ -115,6 +116,7 @@ sealed class TreeSet[A] private (private val tree: RB.Tree[A, Null])(implicit va * bound. */ private[this] final class TreeSetProjection(from: Option[A], until: Option[A]) extends TreeSet[A](tree) { + self: TreeSetProjection^{} => /** * Given a possible new lower bound, chooses and returns the most constraining one (the maximum). @@ -194,7 +196,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/library/src/scala/collection/mutable/UnrolledBuffer.scala b/library/src/scala/collection/mutable/UnrolledBuffer.scala index 4e60b3555a07..aee908369f0f 100644 --- a/library/src/scala/collection/mutable/UnrolledBuffer.scala +++ b/library/src/scala/collection/mutable/UnrolledBuffer.scala @@ -14,6 +14,7 @@ package scala.collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.tailrec import scala.collection.generic.{CommonErrors, DefaultSerializable} import scala.reflect.ClassTag @@ -196,7 +197,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 CommonErrors.indexOutOfBounds(index = idx, max = sz - 1) @@ -208,7 +209,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 @@ -248,7 +249,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] @@ -264,6 +265,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] /** Unrolled buffer node. */ class Unrolled[T: ClassTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) { + this: Unrolled[T]^{} => private[collection] def this() = this(0, new Array[T](unrolledlength), null, null) private[collection] def this(b: UnrolledBuffer[T]) = this(0, new Array[T](unrolledlength), null, b) @@ -378,7 +380,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/library/src/scala/collection/mutable/WeakHashMap.scala b/library/src/scala/collection/mutable/WeakHashMap.scala index e0f592faf9f1..0f8a66f1c840 100644 --- a/library/src/scala/collection/mutable/WeakHashMap.scala +++ b/library/src/scala/collection/mutable/WeakHashMap.scala @@ -15,6 +15,7 @@ package collection package mutable import scala.language.`2.13` +import language.experimental.captureChecking import scala.annotation.nowarn import scala.collection.convert.JavaCollectionWrappers.{JMapWrapper, JMapWrapperLike} @@ -50,7 +51,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/library/src/scala/collection/mutable/package.scala b/library/src/scala/collection/mutable/package.scala index 475aec0afea7..5013839d5587 100644 --- a/library/src/scala/collection/mutable/package.scala +++ b/library/src/scala/collection/mutable/package.scala @@ -13,6 +13,7 @@ package scala.collection import scala.language.`2.13` +import language.experimental.captureChecking package object mutable { @deprecated("Use ArraySeq instead of WrappedArray; it can represent both, boxed and unboxed arrays", "2.13.0") diff --git a/library/src/scala/collection/package.scala b/library/src/scala/collection/package.scala index aced3cb25e03..f43e22b531a7 100644 --- a/library/src/scala/collection/package.scala +++ b/library/src/scala/collection/package.scala @@ -13,6 +13,7 @@ package scala import scala.language.`2.13` +import language.experimental.captureChecking package object collection { @deprecated("Use Iterable instead of Traversable", "2.13.0") @@ -65,7 +66,7 @@ package object collection { /** Splits a sequence into head +: tail. * @return Some((head, tail)) if sequence is non-empty. None otherwise. */ - def unapply[A, CC[_] <: Seq[_], C <: SeqOps[A, CC, C]](t: C with SeqOps[A, CC, C]): Option[(A, C)] = + def unapply[A, CC[_] <: Seq[_], C <: SeqOps[A, CC, C]](t: (C with SeqOps[A, CC, C])^): Option[(A, C^{t})] = if(t.isEmpty) None else Some(t.head -> t.tail) } @@ -75,7 +76,7 @@ package object collection { /** Splits a sequence into init :+ last. * @return Some((init, last)) if sequence is non-empty. None otherwise. */ - def unapply[A, CC[_] <: Seq[_], C <: SeqOps[A, CC, C]](t: C with SeqOps[A, CC, C]): Option[(C, A)] = + def unapply[A, CC[_] <: Seq[_], C <: SeqOps[A, CC, C]](t: (C with SeqOps[A, CC, C])^): Option[(C^{t}, A)] = if(t.isEmpty) None else Some(t.init -> t.last) } diff --git a/library/src/scala/runtime/AbstractPartialFunction.scala b/library/src/scala/runtime/AbstractPartialFunction.scala index 895dac79058b..a3506e45c114 100644 --- a/library/src/scala/runtime/AbstractPartialFunction.scala +++ b/library/src/scala/runtime/AbstractPartialFunction.scala @@ -15,6 +15,8 @@ package runtime import scala.language.`2.13` +import language.experimental.captureChecking + /** `AbstractPartialFunction` reformulates all operations of its supertrait `PartialFunction` * in terms of `isDefinedAt` and `applyOrElse`. * @@ -26,7 +28,7 @@ import scala.language.`2.13` * * This trait is used as a basis for implementation of all partial function literals. */ -abstract class AbstractPartialFunction[@specialized(Specializable.Arg) -T1, @specialized(Specializable.Return) +R] extends Function1[T1, R] with PartialFunction[T1, R] { self => +abstract class AbstractPartialFunction[@specialized(Specializable.Arg) -T1, @specialized(Specializable.Return) +R] extends Function1[T1, R] with PartialFunction[T1, R] { // this method must be overridden for better performance, // for backwards compatibility, fall back to the one inherited from PartialFunction // this assumes the old-school partial functions override the apply method, though diff --git a/tests/neg-custom-args/captures/partial-function.scala.disabled b/tests/neg-custom-args/captures/partial-function.scala.disabled new file mode 100644 index 000000000000..5d75ee193eb6 --- /dev/null +++ b/tests/neg-custom-args/captures/partial-function.scala.disabled @@ -0,0 +1,6 @@ +class A extends caps.SharedCapability: + def even(x: Int) = x % 2 == 0 + +def f(a: A): List[Int] -> List[Int] = + (xs: List[Int]) => xs.collect: // error + case x if a.even(x) => 1 diff --git a/tests/pos-custom-args/captures/partial-function.scala.disabled b/tests/pos-custom-args/captures/partial-function.scala.disabled new file mode 100644 index 000000000000..e8e99148fcda --- /dev/null +++ b/tests/pos-custom-args/captures/partial-function.scala.disabled @@ -0,0 +1,7 @@ +class A extends caps.SharedCapability: + def even(x: Int) = x % 2 == 0 + +def f(a: A): List[Int] ->{a} List[Int] = + (xs: List[Int]) => xs.collect: + case x if a.even(x) => 1 +