summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandar Prokopec <axel22@gmail.com>2012-08-15 15:50:03 +0200
committerAleksandar Prokopec <axel22@gmail.com>2012-08-15 15:50:03 +0200
commit0308ae88026a4a8d427d1a9156c31c0ff8dd2561 (patch)
tree6b67fc0f55bf2b6d088f39a5fe8cc5efb636b89e
parent3ccaa1026e7e74d99fe39c9608e28c48b422e2c9 (diff)
downloadscala-0308ae88026a4a8d427d1a9156c31c0ff8dd2561.tar.gz
scala-0308ae88026a4a8d427d1a9156c31c0ff8dd2561.tar.bz2
scala-0308ae88026a4a8d427d1a9156c31c0ff8dd2561.zip
Fixes SI-6150.
Removes the `VectorReusableCBF` and pattern matching on it in optimized `Vector` methods. Instead, we now have a new `ReusableCBF` instance in `IndexedSeq` and check for equality when trying to optimize `:+`, `+:` and `updated`. This overridden `ReusableCBF` is used by `IndexedSeq`, `immutable.IndexedSeq` and `immutable.Vector`. The net effect is that calling `:+` and similar methods on a `Vector` instance with a `CBF` that came from `IndexedSeq` or somewhere lower in the hierarchy will always create a `Vector` using the optimized method.
-rw-r--r--src/library/scala/collection/IndexedSeq.scala4
-rw-r--r--src/library/scala/collection/generic/GenTraversableFactory.scala2
-rw-r--r--src/library/scala/collection/immutable/IndexedSeq.scala2
-rw-r--r--src/library/scala/collection/immutable/Vector.scala29
-rw-r--r--test/files/run/t6150.scala34
5 files changed, 49 insertions, 22 deletions
diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala
index 56dd0bffff..4d1758fdd3 100644
--- a/src/library/scala/collection/IndexedSeq.scala
+++ b/src/library/scala/collection/IndexedSeq.scala
@@ -29,7 +29,9 @@ trait IndexedSeq[+A] extends Seq[A]
* @define Coll `IndexedSeq`
*/
object IndexedSeq extends SeqFactory[IndexedSeq] {
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
+ override lazy val ReusableCBF: GenericCanBuildFrom[Nothing] = new ReusableCBF
+
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
def newBuilder[A]: Builder[A, IndexedSeq[A]] = immutable.IndexedSeq.newBuilder[A]
}
diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala
index 2aaf93de05..3d5306621a 100644
--- a/src/library/scala/collection/generic/GenTraversableFactory.scala
+++ b/src/library/scala/collection/generic/GenTraversableFactory.scala
@@ -40,7 +40,7 @@ abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTrav
// A default implementation of GenericCanBuildFrom which can be cast
// to whatever is desired.
- private class ReusableCBF extends GenericCanBuildFrom[Nothing] {
+ private[collection] class ReusableCBF extends GenericCanBuildFrom[Nothing] {
override def apply() = newBuilder[Nothing]
}
// Working around SI-4789 by using a lazy val instead of an object.
diff --git a/src/library/scala/collection/immutable/IndexedSeq.scala b/src/library/scala/collection/immutable/IndexedSeq.scala
index b37edc4254..3abac932e6 100644
--- a/src/library/scala/collection/immutable/IndexedSeq.scala
+++ b/src/library/scala/collection/immutable/IndexedSeq.scala
@@ -36,6 +36,6 @@ object IndexedSeq extends SeqFactory[IndexedSeq] {
def length = buf.length
def apply(idx: Int) = buf.apply(idx)
}
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
def newBuilder[A]: Builder[A, IndexedSeq[A]] = Vector.newBuilder[A]
}
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index 4dfe147a65..d0098e8420 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -18,14 +18,8 @@ import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
*/
object Vector extends SeqFactory[Vector] {
- private[collection] class VectorReusableCBF extends GenericCanBuildFrom[Nothing] {
- override def apply() = newBuilder[Nothing]
- }
-
- private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF
-
@inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
- VectorReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
+ IndexedSeq.ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A]
private[immutable] val NIL = new Vector[Nothing](0, 0, 0)
@inline override def empty[A]: Vector[A] = NIL
@@ -146,20 +140,17 @@ override def companion: GenericCompanion[Vector] = Vector
// SeqLike api
- @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => updateAt(index, elem).asInstanceOf[That] // just ignore bf
- case _ => super.updated(index, elem)(bf)
- }
+ @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) updateAt(index, elem).asInstanceOf[That] // just ignore bf
+ else super.updated(index, elem)(bf)
- @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => appendFront(elem).asInstanceOf[That] // just ignore bf
- case _ => super.+:(elem)(bf)
- }
+ @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf
+ else super.+:(elem)(bf)
- @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => appendBack(elem).asInstanceOf[That] // just ignore bf
- case _ => super.:+(elem)(bf)
- }
+ @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf
+ else super.:+(elem)(bf)
override def take(n: Int): Vector[A] = {
if (n <= 0)
diff --git a/test/files/run/t6150.scala b/test/files/run/t6150.scala
new file mode 100644
index 0000000000..1b3de0c50a
--- /dev/null
+++ b/test/files/run/t6150.scala
@@ -0,0 +1,34 @@
+
+
+
+import collection._
+
+
+
+object Test extends App {
+
+ val cbf1 = implicitly[generic.CanBuildFrom[Vector[Int], Int, IndexedSeq[Int]]]
+ val cbf2 = implicitly[generic.CanBuildFrom[immutable.IndexedSeq[Int], Int, IndexedSeq[Int]]]
+ val cbf3 = implicitly[generic.CanBuildFrom[IndexedSeq[Int], Int, IndexedSeq[Int]]]
+
+ def check[C](v: C) = {
+ assert(v == Vector(1, 2, 3, 4))
+ assert(v.isInstanceOf[Vector[_]])
+ }
+
+ val v = immutable.Vector(1, 2, 3)
+
+ check(v.:+(4)(cbf1))
+ check(v.:+(4)(cbf2))
+ check(v.:+(4)(cbf3))
+
+ val iiv: immutable.IndexedSeq[Int] = immutable.Vector(1, 2, 3)
+
+ check(iiv.:+(4)(cbf2))
+ check(iiv.:+(4)(cbf3))
+
+ val iv: IndexedSeq[Int] = immutable.Vector(1, 2, 3)
+
+ check(iv.:+(4)(cbf3))
+
+}