From ebfcb42aec35b3876457fbbc219d78fd2d384cab Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 22 Mar 2018 18:58:02 +0100 Subject: [PATCH 1/6] Add @uncheckedVariance annotations to protected[this] members --- .../src/main/scala/strawman/collection/BitSet.scala | 3 ++- .../main/scala/strawman/collection/Iterable.scala | 13 +++++++------ .../src/main/scala/strawman/collection/Map.scala | 8 ++++---- .../main/scala/strawman/collection/SortedMap.scala | 8 ++++---- .../main/scala/strawman/collection/SortedSet.scala | 6 +++--- .../collection/immutable/ImmutableArray.scala | 6 +++--- .../strawman/collection/immutable/IntMap.scala | 5 +++-- .../strawman/collection/immutable/LazyList.scala | 4 ++-- .../strawman/collection/immutable/LongMap.scala | 6 +++--- .../scala/strawman/collection/immutable/Map.scala | 5 +++-- .../strawman/collection/immutable/SortedMap.scala | 5 +++-- 11 files changed, 37 insertions(+), 32 deletions(-) diff --git a/collections/src/main/scala/strawman/collection/BitSet.scala b/collections/src/main/scala/strawman/collection/BitSet.scala index 77157445bd..1f9b02137e 100644 --- a/collections/src/main/scala/strawman/collection/BitSet.scala +++ b/collections/src/main/scala/strawman/collection/BitSet.scala @@ -5,6 +5,7 @@ import strawman.collection.mutable.Builder import scala.{Array, Boolean, Int, Long, Option, Ordering, Unit, `inline`} import scala.Predef.{assert, intWrapper} +import annotation.unchecked.uncheckedVariance /** Base type of bitsets. * @@ -37,7 +38,7 @@ trait BitSetOps[+C <: BitSet with BitSetOps[C]] def bitSetFactory: SpecificIterableFactory[Int, BitSetC] - protected[this] type BitSetC = C + protected[this] type BitSetC = C @uncheckedVariance final def ordering: Ordering[Int] = Ordering.Int diff --git a/collections/src/main/scala/strawman/collection/Iterable.scala b/collections/src/main/scala/strawman/collection/Iterable.scala index ae1b87d17f..209dc2140d 100644 --- a/collections/src/main/scala/strawman/collection/Iterable.scala +++ b/collections/src/main/scala/strawman/collection/Iterable.scala @@ -7,6 +7,7 @@ import scala.reflect.ClassTag import scala.{Any, AnyRef, Array, Boolean, Either, `inline`, Int, None, Numeric, Option, Ordering, PartialFunction, StringContext, Some, Unit, deprecated, IllegalArgumentException, Function1, deprecatedOverriding} import java.lang.{String, UnsupportedOperationException} import scala.Predef.<:< +import annotation.unchecked.uncheckedVariance import strawman.collection.mutable.{ArrayBuffer, Builder, StringBuilder} import java.lang.String @@ -26,8 +27,8 @@ trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterabl //TODO scalac generates an override for this in AbstractMap; Making it final leads to a VerifyError protected[this] def coll: this.type = this - protected[this] def fromSpecificIterable(coll: Iterable[A]): IterableCC[A] = iterableFactory.from(coll) - protected[this] def newSpecificBuilder(): Builder[A, IterableCC[A]] = iterableFactory.newBuilder[A]() + protected[this] def fromSpecificIterable(coll: Iterable[A @uncheckedVariance]): IterableCC[A] @uncheckedVariance = iterableFactory.from(coll) + protected[this] def newSpecificBuilder(): Builder[A, IterableCC[A]] @uncheckedVariance = iterableFactory.newBuilder[A]() def iterableFactory: IterableFactory[IterableCC] = Iterable } @@ -68,7 +69,7 @@ trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterabl */ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with IterableOnceOps[A, CC, C] { - protected[this] type IterableCC[X] = CC[X] + protected[this] type IterableCC[X] = CC[X] @uncheckedVariance /** * @return This collection as an `Iterable[A]`. No new collection will be built if `this` is already an `Iterable[A]`. @@ -87,7 +88,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * the elements of the resulting collections). In other words, this methods defines * the evaluation model of the collection. */ - protected[this] def fromSpecificIterable(coll: Iterable[A]): C + protected[this] def fromSpecificIterable(coll: Iterable[A @uncheckedVariance]): C /** Similar to `fromSpecificIterable`, but for a (possibly) different type of element. * Note that the return type is now `CC[E]`. @@ -107,7 +108,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable * As a consequence, operations should preferably be implemented with `fromSpecificIterable` * instead of this method. */ - protected[this] def newSpecificBuilder(): Builder[A, C] + protected[this] def newSpecificBuilder(): Builder[A @uncheckedVariance, C] /** Selects the first element of this $coll. * $orderDependent @@ -326,7 +327,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable */ class WithFilter(p: A => Boolean) extends collection.WithFilter[A, CC] { - protected[this] def filtered = new View.Filter(IterableOps.this, p, isFlipped = false) + protected[this] def filtered: View.Filter[A @uncheckedVariance] = new View.Filter(IterableOps.this, p, isFlipped = false) def map[B](f: A => B): CC[B] = iterableFactory.from(new View.Map(filtered, f)) diff --git a/collections/src/main/scala/strawman/collection/Map.scala b/collections/src/main/scala/strawman/collection/Map.scala index 54e3bd53a4..d59c0c73bd 100644 --- a/collections/src/main/scala/strawman/collection/Map.scala +++ b/collections/src/main/scala/strawman/collection/Map.scala @@ -15,12 +15,12 @@ trait Map[K, +V] with MapOps[K, V, Map, Map[K, V]] with Equals { - override protected[this] def fromSpecificIterable(coll: Iterable[(K, V)]): MapCC[K, V] = mapFactory.from(coll) - override protected[this] def newSpecificBuilder(): mutable.Builder[(K, V), MapCC[K, V]] = mapFactory.newBuilder[K, V]() + override protected[this] def fromSpecificIterable(coll: Iterable[(K, V)] @uncheckedVariance): MapCC[K, V] @uncheckedVariance = mapFactory.from(coll) + override protected[this] def newSpecificBuilder(): mutable.Builder[(K, V), MapCC[K, V]] @uncheckedVariance = mapFactory.newBuilder[K, V]() def mapFactory: strawman.collection.MapFactory[MapCC] = Map - def empty: MapCC[K, V] = mapFactory.empty + def empty: MapCC[K, V] @uncheckedVariance = mapFactory.empty def canEqual(that: Any): Boolean = true @@ -62,7 +62,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] override def view: MapView[K, V] = new MapView.Id(this) - protected[this] type MapCC[K, V] = CC[K, V] + protected[this] type MapCC[K, V] = CC[K, V] @uncheckedVariance /** Similar to `fromIterable`, but returns a Map collection type. * Note that the return type is now `CC[K2, V2]` aka `MapCC[K2, V2]` rather than `IterableCC[(K2, V2)]`. diff --git a/collections/src/main/scala/strawman/collection/SortedMap.scala b/collections/src/main/scala/strawman/collection/SortedMap.scala index 367ffe0dc5..5625bcc78d 100644 --- a/collections/src/main/scala/strawman/collection/SortedMap.scala +++ b/collections/src/main/scala/strawman/collection/SortedMap.scala @@ -14,19 +14,19 @@ trait SortedMap[K, +V] def unsorted: Map[K, V] = this - override protected[this] def fromSpecificIterable(coll: Iterable[(K, V)]): SortedMapCC[K, V] = sortedMapFactory.from(coll) - override protected[this] def newSpecificBuilder(): mutable.Builder[(K, V), SortedMapCC[K, V]] = sortedMapFactory.newBuilder[K, V]() + override protected[this] def fromSpecificIterable(coll: Iterable[(K, V)] @uncheckedVariance): SortedMapCC[K, V] @uncheckedVariance = sortedMapFactory.from(coll) + override protected[this] def newSpecificBuilder(): mutable.Builder[(K, V), SortedMapCC[K, V]] @uncheckedVariance = sortedMapFactory.newBuilder[K, V]() def sortedMapFactory: SortedMapFactory[SortedMapCC] = SortedMap - override def empty: SortedMapCC[K, V] = sortedMapFactory.empty + override def empty: SortedMapCC[K, V] @uncheckedVariance = sortedMapFactory.empty } trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], +C <: SortedMapOps[K, V, CC, C]] extends MapOps[K, V, Map, C] with SortedOps[K, C] { - protected[this] type SortedMapCC[K, V] = CC[K, V] + protected[this] type SortedMapCC[K, V] = CC[K, V] @uncheckedVariance def sortedMapFactory: SortedMapFactory[SortedMapCC] diff --git a/collections/src/main/scala/strawman/collection/SortedSet.scala b/collections/src/main/scala/strawman/collection/SortedSet.scala index 64f518099f..6372af4d38 100644 --- a/collections/src/main/scala/strawman/collection/SortedSet.scala +++ b/collections/src/main/scala/strawman/collection/SortedSet.scala @@ -7,8 +7,8 @@ import scala.annotation.unchecked.uncheckedVariance trait SortedSet[A] extends Set[A] with SortedSetOps[A, SortedSet, SortedSet[A]] { def unsorted: Set[A] = this - override protected[this] def fromSpecificIterable(coll: Iterable[A]): SortedIterableCC[A] = sortedIterableFactory.from(coll) - override protected[this] def newSpecificBuilder(): mutable.Builder[A, SortedIterableCC[A]] = sortedIterableFactory.newBuilder[A]() + override protected[this] def fromSpecificIterable(coll: Iterable[A] @uncheckedVariance): SortedIterableCC[A] @uncheckedVariance = sortedIterableFactory.from(coll) + override protected[this] def newSpecificBuilder(): mutable.Builder[A, SortedIterableCC[A]] @uncheckedVariance = sortedIterableFactory.newBuilder[A]() def sortedIterableFactory: SortedIterableFactory[SortedIterableCC] = SortedSet @@ -19,7 +19,7 @@ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] extends SetOps[A, Set, C] with SortedOps[A, C] { - protected[this] type SortedIterableCC[X] = CC[X] + protected[this] type SortedIterableCC[X] = CC[X] @uncheckedVariance def sortedIterableFactory: SortedIterableFactory[SortedIterableCC] diff --git a/collections/src/main/scala/strawman/collection/immutable/ImmutableArray.scala b/collections/src/main/scala/strawman/collection/immutable/ImmutableArray.scala index 869b63d9bb..af0c2766cc 100644 --- a/collections/src/main/scala/strawman/collection/immutable/ImmutableArray.scala +++ b/collections/src/main/scala/strawman/collection/immutable/ImmutableArray.scala @@ -26,7 +26,7 @@ sealed abstract class ImmutableArray[+A] with StrictOptimizedSeqOps[A, ImmutableArray, ImmutableArray[A]] { /** The tag of the element type */ - protected[this] def elemTag: ClassTag[A] + protected[this] def elemTag: ClassTag[A] @uncheckedVariance override def iterableFactory: SeqFactory[ImmutableArray] = ImmutableArray.untagged @@ -36,9 +36,9 @@ sealed abstract class ImmutableArray[+A] // uncheckedVariance should be safe: Array[A] for reference types A is covariant at the JVM level. Array[A] for // primitive types A can only be widened to Array[Any] which erases to Object. - override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[A]): ImmutableArray[A] = ImmutableArray.from[A](coll)(elemTag) + override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[A] @uncheckedVariance): ImmutableArray[A] = ImmutableArray.from[A](coll)(elemTag) - override protected[this] def newSpecificBuilder(): Builder[A, ImmutableArray[A]] = ImmutableArray.newBuilder[A]()(elemTag) + override protected[this] def newSpecificBuilder(): Builder[A, ImmutableArray[A]] @uncheckedVariance = ImmutableArray.newBuilder[A]()(elemTag) @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): A diff --git a/collections/src/main/scala/strawman/collection/immutable/IntMap.scala b/collections/src/main/scala/strawman/collection/immutable/IntMap.scala index e60098749b..4383b50635 100644 --- a/collections/src/main/scala/strawman/collection/immutable/IntMap.scala +++ b/collections/src/main/scala/strawman/collection/immutable/IntMap.scala @@ -15,6 +15,7 @@ import strawman.collection import strawman.collection.generic.BitOperations import strawman.collection.mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec +import scala.annotation.unchecked.uncheckedVariance /** Utility class for integer maps. * @author David MacIver @@ -169,7 +170,7 @@ sealed abstract class IntMap[+T] extends Map[Int, T] with StrictOptimizedIterableOps[(Int, T), Iterable, IntMap[T]] with Serializable { - override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[(Int, T)]): IntMap[T] = + override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[(Int, T) @uncheckedVariance]): IntMap[T] = intMapFromIterable[T](coll) protected[this] def intMapFromIterable[V2](coll: strawman.collection.Iterable[(Int, V2)]): IntMap[V2] = { val b = IntMap.newBuilder[V2]() @@ -177,7 +178,7 @@ sealed abstract class IntMap[+T] extends Map[Int, T] b.addAll(coll) b.result() } - override protected[this] def newSpecificBuilder(): Builder[(Int, T), IntMap[T]] = + override protected[this] def newSpecificBuilder(): Builder[(Int, T), IntMap[T]] @uncheckedVariance = new ImmutableBuilder[(Int, T), IntMap[T]](empty) { def addOne(elem: (Int, T)): this.type = { elems = elems + elem; this } } diff --git a/collections/src/main/scala/strawman/collection/immutable/LazyList.scala b/collections/src/main/scala/strawman/collection/immutable/LazyList.scala index 2e3d109967..b531c96771 100644 --- a/collections/src/main/scala/strawman/collection/immutable/LazyList.scala +++ b/collections/src/main/scala/strawman/collection/immutable/LazyList.scala @@ -231,7 +231,7 @@ sealed private[immutable] trait LazyListOps[+A, +CC[+X] <: LinearSeq[X] with Laz def tail: C - protected[this] def cons[T](hd: => T, tl: => CC[T]): CC[T] + protected[this] def cons[T](hd: => T, tl: => CC[T] @uncheckedVariance): CC[T] /** Forces evaluation of the whole `LazyList` and returns it. * @@ -466,7 +466,7 @@ sealed private[immutable] trait LazyListOps[+A, +CC[+X] <: LinearSeq[X] with Laz sealed private[immutable] trait LazyListFactory[+CC[+X] <: LinearSeq[X] with LazyListOps[X, CC, CC[X]]] extends SeqFactory[CC] { - protected[this] def newCons[T](hd: => T, tl: => CC[T]): CC[T] + protected[this] def newCons[T](hd: => T, tl: => CC[T] @uncheckedVariance): CC[T] private[immutable] def withFilter[A](l: CC[A] @uncheckedVariance, p: A => Boolean): collection.WithFilter[A, CC] = new WithFilter[A](l, p) diff --git a/collections/src/main/scala/strawman/collection/immutable/LongMap.scala b/collections/src/main/scala/strawman/collection/immutable/LongMap.scala index 9b737fc957..748737e7c2 100644 --- a/collections/src/main/scala/strawman/collection/immutable/LongMap.scala +++ b/collections/src/main/scala/strawman/collection/immutable/LongMap.scala @@ -14,7 +14,7 @@ import java.lang.IllegalStateException import strawman.collection.generic.BitOperations import strawman.collection.mutable.{Builder, ImmutableBuilder, ListBuffer} import scala.annotation.tailrec -import scala.annotation.tailrec +import annotation.unchecked.uncheckedVariance /** Utility class for long maps. * @author David MacIver @@ -161,14 +161,14 @@ sealed abstract class LongMap[+T] extends Map[Long, T] with StrictOptimizedIterableOps[(Long, T), Iterable, LongMap[T]] with Serializable { - override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[(Long, T)]): LongMap[T] = { + override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[(Long, T)] @uncheckedVariance): LongMap[T] = { //TODO should this be the default implementation of this method in StrictOptimizedIterableOps? val b = newSpecificBuilder() b.sizeHint(coll) b.addAll(coll) b.result() } - override protected[this] def newSpecificBuilder(): Builder[(Long, T), LongMap[T]] = + override protected[this] def newSpecificBuilder(): Builder[(Long, T), LongMap[T]] @uncheckedVariance = new ImmutableBuilder[(Long, T), LongMap[T]](empty) { def addOne(elem: (Long, T)): this.type = { elems = elems + elem; this } } diff --git a/collections/src/main/scala/strawman/collection/immutable/Map.scala b/collections/src/main/scala/strawman/collection/immutable/Map.scala index 9fd881b59b..dceabb02f3 100644 --- a/collections/src/main/scala/strawman/collection/immutable/Map.scala +++ b/collections/src/main/scala/strawman/collection/immutable/Map.scala @@ -6,6 +6,7 @@ import strawman.collection.mutable.Builder import scala.{Any, Boolean, `inline`, Int, None, NoSuchElementException, Nothing, Option, Some, Serializable, SerialVersionUID, Unit} import scala.Predef.<:< +import annotation.unchecked.uncheckedVariance /** Base type of immutable Maps */ trait Map[K, +V] @@ -152,10 +153,10 @@ object Map extends MapFactory[Map] { override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) - override protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)]): WithDefault[K, V] = + override protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)] @uncheckedVariance): WithDefault[K, V] = new WithDefault[K, V](mapFactory.from(coll), defaultValue) - override protected[this] def newSpecificBuilder(): Builder[(K, V), WithDefault[K, V]] = + override protected[this] def newSpecificBuilder(): Builder[(K, V), WithDefault[K, V]] @uncheckedVariance = Map.newBuilder().mapResult((p: Map[K, V]) => new WithDefault[K, V](p, defaultValue)) } diff --git a/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala b/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala index 4cdca0da17..09d4fa3ae5 100644 --- a/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala +++ b/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala @@ -4,6 +4,7 @@ package immutable import strawman.collection.mutable.Builder import scala.{Option, Ordering, `inline`, Serializable, SerialVersionUID} +import annotation.unchecked.uncheckedVariance trait SortedMap[K, +V] extends Map[K, V] @@ -96,10 +97,10 @@ object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) - override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[(K, V)]): WithDefault[K, V] = + override protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[(K, V)] @uncheckedVariance): WithDefault[K, V] = new WithDefault[K, V](sortedMapFactory.from(coll), defaultValue) - override protected[this] def newSpecificBuilder(): Builder[(K, V), WithDefault[K, V]] = + override protected[this] def newSpecificBuilder(): Builder[(K, V), WithDefault[K, V]] @uncheckedVariance = SortedMap.newBuilder().mapResult((p: SortedMap[K, V]) => new WithDefault[K, V](p, defaultValue)) } } \ No newline at end of file From d59598dad1d96a02ed0e0b44f2fe691037f47700 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 22 Mar 2018 22:08:15 +0100 Subject: [PATCH 2/6] Disable WithFilter specializations The specializations were all unsound since they typically returned WithFilter of a collection {Iterable/Map/Set} where a mutable or immutable collection was required. We need to either drop them or come up with a sound design. --- .../scala/strawman/collection/SortedMultiSet.scala | 5 ++++- .../src/main/scala/strawman/collection/Map.scala | 14 +------------- .../main/scala/strawman/collection/SortedMap.scala | 4 +++- .../main/scala/strawman/collection/SortedSet.scala | 5 ++++- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala b/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala index 07a8b103c3..0aaaf4a35f 100644 --- a/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala +++ b/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala @@ -64,6 +64,9 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] override def withFilter(p: A => Boolean): SortedWithFilter = new SortedWithFilter(p) + type SortedWithFilter = Withfilter + +/* /** Specialize `WithFilter` for sorted collections * * @define coll sorted collection @@ -77,7 +80,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] override def withFilter(q: A => Boolean): SortedWithFilter = new SortedWithFilter(a => p(a) && q(a)) } - +*/ /** Builds a new sorted multiset by applying a function to all elements of this sorted multiset. * * @param f the function to apply to each element. diff --git a/collections/src/main/scala/strawman/collection/Map.scala b/collections/src/main/scala/strawman/collection/Map.scala index d59c0c73bd..970a37af6d 100644 --- a/collections/src/main/scala/strawman/collection/Map.scala +++ b/collections/src/main/scala/strawman/collection/Map.scala @@ -213,19 +213,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] override def withFilter(p: ((K, V)) => Boolean): MapWithFilter = new MapWithFilter(p) - /** Specializes `WithFilter` for Map collection types - * - * @define coll map collection - */ - class MapWithFilter(p: ((K, V)) => Boolean) extends WithFilter(p) { - - def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = mapFactory.from(new View.Map(filtered, f)) - - def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = mapFactory.from(new View.FlatMap(filtered, f)) - - override def withFilter(q: ((K, V)) => Boolean): MapWithFilter = new MapWithFilter(kv => p(kv) && q(kv)) - - } + type MapWithFilter = WithFilter /** Builds a new map by applying a function to all elements of this $coll. * diff --git a/collections/src/main/scala/strawman/collection/SortedMap.scala b/collections/src/main/scala/strawman/collection/SortedMap.scala index 5625bcc78d..11d13c751b 100644 --- a/collections/src/main/scala/strawman/collection/SortedMap.scala +++ b/collections/src/main/scala/strawman/collection/SortedMap.scala @@ -119,6 +119,8 @@ trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], override def withFilter(p: ((K, V)) => Boolean): SortedMapWithFilter = new SortedMapWithFilter(p) + type SortedMapWithFilter = MapWithFilter +/* /** Specializes `MapWithFilter` for sorted Map collections * * @define coll sorted map collection @@ -134,7 +136,7 @@ trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], override def withFilter(q: ((K, V)) => Boolean): SortedMapWithFilter = new SortedMapWithFilter(kv => p(kv) && q(kv)) } - +*/ // And finally, we add new overloads taking an ordering /** Builds a new sorted map by applying a function to all elements of this $coll. * diff --git a/collections/src/main/scala/strawman/collection/SortedSet.scala b/collections/src/main/scala/strawman/collection/SortedSet.scala index 6372af4d38..6d131486ca 100644 --- a/collections/src/main/scala/strawman/collection/SortedSet.scala +++ b/collections/src/main/scala/strawman/collection/SortedSet.scala @@ -68,6 +68,9 @@ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] override def withFilter(p: A => Boolean): SortedWithFilter = new SortedWithFilter(p) + type SortedWithFilter = WithFilter + +/* /** Specialize `WithFilter` for sorted collections * * @define coll sorted collection @@ -79,8 +82,8 @@ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedIterableFactory.from(new View.FlatMap(filtered, f)) override def withFilter(q: A => Boolean): SortedWithFilter = new SortedWithFilter(a => p(a) && q(a)) - } +*/ /** Builds a new sorted collection by applying a function to all elements of this $coll. * From f9aae5d1c35628621cb1cfe5f21e003d73b60331 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 22 Mar 2018 22:10:27 +0100 Subject: [PATCH 3/6] Override specialized ArrayDeque methods in Queue and Stack There were three methods specialized in ArrayDeque to return some structure of ArrayDeques instead of the underlying collection type. These were inherited without overridng by Queue and Stack. This means the contract is broken: The type says that e.g. sliding returns an Iterator[Queue] but in reality it returns an Iterator[ArrayDeque]. --- .../src/main/scala/strawman/collection/mutable/Queue.scala | 4 ++++ .../src/main/scala/strawman/collection/mutable/Stack.scala | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/collections/src/main/scala/strawman/collection/mutable/Queue.scala b/collections/src/main/scala/strawman/collection/mutable/Queue.scala index 90f0f8262c..bf76bffec5 100644 --- a/collections/src/main/scala/strawman/collection/mutable/Queue.scala +++ b/collections/src/main/scala/strawman/collection/mutable/Queue.scala @@ -41,6 +41,10 @@ class Queue[A] protected (array: Array[AnyRef], start: Int, end: Int) override def iterableFactory: SeqFactory[Queue] = Queue + override def grouped(n: Int) = super[IndexedSeqOps].grouped(n) + override def reverse = super[IndexedSeqOps].reverse + override def sliding(window: Int, step: Int) = super[IndexedSeqOps].sliding(window, step) + /** * Add elements to the end of this queue * diff --git a/collections/src/main/scala/strawman/collection/mutable/Stack.scala b/collections/src/main/scala/strawman/collection/mutable/Stack.scala index 54f07cc943..9fc0464663 100644 --- a/collections/src/main/scala/strawman/collection/mutable/Stack.scala +++ b/collections/src/main/scala/strawman/collection/mutable/Stack.scala @@ -33,6 +33,10 @@ class Stack[A] protected (array: Array[AnyRef], start: Int, end: Int) override def iterableFactory: SeqFactory[Stack] = Stack + override def grouped(n: Int) = super[IndexedSeqOps].grouped(n) + override def reverse = super[IndexedSeqOps].reverse + override def sliding(window: Int, step: Int) = super[IndexedSeqOps].sliding(window, step) + /** * Add elements to the top of this stack * From 6bacede0c0a02106426ca872209d6d7394e31f6e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 22 Mar 2018 22:27:36 +0100 Subject: [PATCH 4/6] Use fully qualified import for annotation --- collections/src/main/scala/strawman/collection/BitSet.scala | 2 +- collections/src/main/scala/strawman/collection/Iterable.scala | 2 +- .../src/main/scala/strawman/collection/immutable/LongMap.scala | 2 +- .../src/main/scala/strawman/collection/immutable/Map.scala | 2 +- .../main/scala/strawman/collection/immutable/SortedMap.scala | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/collections/src/main/scala/strawman/collection/BitSet.scala b/collections/src/main/scala/strawman/collection/BitSet.scala index 1f9b02137e..7d98f8da3d 100644 --- a/collections/src/main/scala/strawman/collection/BitSet.scala +++ b/collections/src/main/scala/strawman/collection/BitSet.scala @@ -5,7 +5,7 @@ import strawman.collection.mutable.Builder import scala.{Array, Boolean, Int, Long, Option, Ordering, Unit, `inline`} import scala.Predef.{assert, intWrapper} -import annotation.unchecked.uncheckedVariance +import scala.annotation.unchecked.uncheckedVariance /** Base type of bitsets. * diff --git a/collections/src/main/scala/strawman/collection/Iterable.scala b/collections/src/main/scala/strawman/collection/Iterable.scala index 209dc2140d..3fbd06ee14 100644 --- a/collections/src/main/scala/strawman/collection/Iterable.scala +++ b/collections/src/main/scala/strawman/collection/Iterable.scala @@ -7,7 +7,7 @@ import scala.reflect.ClassTag import scala.{Any, AnyRef, Array, Boolean, Either, `inline`, Int, None, Numeric, Option, Ordering, PartialFunction, StringContext, Some, Unit, deprecated, IllegalArgumentException, Function1, deprecatedOverriding} import java.lang.{String, UnsupportedOperationException} import scala.Predef.<:< -import annotation.unchecked.uncheckedVariance +import scala.annotation.unchecked.uncheckedVariance import strawman.collection.mutable.{ArrayBuffer, Builder, StringBuilder} import java.lang.String diff --git a/collections/src/main/scala/strawman/collection/immutable/LongMap.scala b/collections/src/main/scala/strawman/collection/immutable/LongMap.scala index 748737e7c2..e36b4a65ff 100644 --- a/collections/src/main/scala/strawman/collection/immutable/LongMap.scala +++ b/collections/src/main/scala/strawman/collection/immutable/LongMap.scala @@ -14,7 +14,7 @@ import java.lang.IllegalStateException import strawman.collection.generic.BitOperations import strawman.collection.mutable.{Builder, ImmutableBuilder, ListBuffer} import scala.annotation.tailrec -import annotation.unchecked.uncheckedVariance +import scala.annotation.unchecked.uncheckedVariance /** Utility class for long maps. * @author David MacIver diff --git a/collections/src/main/scala/strawman/collection/immutable/Map.scala b/collections/src/main/scala/strawman/collection/immutable/Map.scala index dceabb02f3..e66b06cf19 100644 --- a/collections/src/main/scala/strawman/collection/immutable/Map.scala +++ b/collections/src/main/scala/strawman/collection/immutable/Map.scala @@ -6,7 +6,7 @@ import strawman.collection.mutable.Builder import scala.{Any, Boolean, `inline`, Int, None, NoSuchElementException, Nothing, Option, Some, Serializable, SerialVersionUID, Unit} import scala.Predef.<:< -import annotation.unchecked.uncheckedVariance +import scala.annotation.unchecked.uncheckedVariance /** Base type of immutable Maps */ trait Map[K, +V] diff --git a/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala b/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala index 09d4fa3ae5..308f0f7dab 100644 --- a/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala +++ b/collections/src/main/scala/strawman/collection/immutable/SortedMap.scala @@ -4,7 +4,7 @@ package immutable import strawman.collection.mutable.Builder import scala.{Option, Ordering, `inline`, Serializable, SerialVersionUID} -import annotation.unchecked.uncheckedVariance +import scala.annotation.unchecked.uncheckedVariance trait SortedMap[K, +V] extends Map[K, V] From fdef5988c0193af45802dd35d5bb53f0ea08d245 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 22 Mar 2018 22:37:58 +0100 Subject: [PATCH 5/6] Fix typo --- .../src/main/scala/strawman/collection/SortedMultiSet.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala b/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala index 0aaaf4a35f..a3b344e60c 100644 --- a/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala +++ b/collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala @@ -64,7 +64,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] override def withFilter(p: A => Boolean): SortedWithFilter = new SortedWithFilter(p) - type SortedWithFilter = Withfilter + type SortedWithFilter = WithFilter /* /** Specialize `WithFilter` for sorted collections From 28d23833c67c0d000aff117cc624c3b91c1dea38 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 22 Mar 2018 22:59:26 +0100 Subject: [PATCH 6/6] Disable some WithFilter tests --- .../strawman/collection/WithFilterTest.scala | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/junit/src/test/scala/strawman/collection/WithFilterTest.scala b/test/junit/src/test/scala/strawman/collection/WithFilterTest.scala index d2f11b3e5d..bac94a6fcc 100644 --- a/test/junit/src/test/scala/strawman/collection/WithFilterTest.scala +++ b/test/junit/src/test/scala/strawman/collection/WithFilterTest.scala @@ -25,8 +25,9 @@ class WithFilterTest { (k, v) <- Map(1 -> 'a', 2 -> 'b', 3 -> 'c') if k % 2 == 0 } yield (v, k) - val xs1t: Map[Char, Int] = xs1 - assert(xs1 == Map('b' -> 2)) +// Disabled, awaiting refactoring of WithFilter +// val xs1t: Map[Char, Int] = xs1 +// assert(xs1 == Map('b' -> 2)) val xs2 = for { @@ -44,8 +45,9 @@ class WithFilterTest { x <- TreeSet(1, 2, 3) if x % 2 == 0 } yield x + 1 - val xs1t: TreeSet[Int] = xs1 - assert(xs1 == TreeSet(3)) +// Disabled, awaiting refactoring of WithFilter +// val xs1t: TreeSet[Int] = xs1 +// assert(xs1 == TreeSet(3)) } @Test @@ -55,8 +57,9 @@ class WithFilterTest { (k, v) <- TreeMap(1 -> 'a', 2 -> 'b', 3 -> 'c') if k % 2 == 0 } yield (v, k) - val xs1t: TreeMap[Char, Int] = xs1 - assert(xs1 == TreeMap('b' -> 2)) +// Disabled, awaiting refactoring of WithFilter +// val xs1t: TreeMap[Char, Int] = xs1 +// assert(xs1 == TreeMap('b' -> 2)) } }