Skip to content

Commit e980f0c

Browse files
committed
[nomerge] Avoid allocations of reusable CanBuildFroms
(For 2.12.x's eyes only.) Use vals to cache a single instance of stateless CanBuildFrom instances. These are cast by the existing `implicit def` to the suitable generic type. This pattern was already used in some places -- this PR applies it systematically across `collection.{mutable,immutable}`. The `CanBuildFrom` instances for arrays and wrapped arrays are cached for each primitive type, Unit, and Object. Each of these instances is backed by a dedicated subclass of CanBuildFrom that avoids subsequent dispatch on the `ClassTag[T]`.
1 parent 8a63f12 commit e980f0c

35 files changed

+288
-92
lines changed

library/src/mima-filters/2.12.0.forwards.excludes

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,6 @@ ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.L
5656
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.HashMap#HashMap1.foreachEntry")
5757
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.HashMap#HashMapCollision1.foreachEntry")
5858
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.hashing.MurmurHash3.product2Hash")
59-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.hashing.MurmurHash3.emptyMapHash")
59+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.hashing.MurmurHash3.emptyMapHash")
60+
61+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.TraversableView.noBuilder")

library/src/scala/Array.scala

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,79 @@ object Array extends FallbackArrayBuilding {
6161
val emptyShortArray = new Array[Short](0)
6262
val emptyObjectArray = new Array[Object](0)
6363

64-
implicit def canBuildFrom[T](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] =
64+
implicit def canBuildFrom[T](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = {
65+
val tag = implicitly[ClassTag[T]]
66+
val cls = tag.runtimeClass
67+
(if (cls.isPrimitive) {
68+
cls match {
69+
case java.lang.Byte.TYPE => cbfByteArray
70+
case java.lang.Short.TYPE => cbfShortArray
71+
case java.lang.Character.TYPE => cbfCharArray
72+
case java.lang.Integer.TYPE => cbfIntArray
73+
case java.lang.Long.TYPE => cbfLongArray
74+
case java.lang.Float.TYPE => cbfFloatArray
75+
case java.lang.Double.TYPE => cbfDoubleArray
76+
case java.lang.Boolean.TYPE => cbfBooleanArray
77+
case java.lang.Void.TYPE => cbfUnitArray
78+
}
79+
} else if (cls == ObjectClass) {
80+
cbfObjectArray
81+
} else {
82+
refCBF[T with AnyRef](tag.asInstanceOf[ClassTag[T with AnyRef]])
83+
}).asInstanceOf[CanBuildFrom[Array[_], T, Array[T]]]
84+
}
85+
private[this] val ObjectClass = classOf[Object]
86+
87+
private[this] val cbfBooleanArray = new CanBuildFrom[Array[_], Boolean, Array[Boolean]] {
88+
def apply(from: Array[_]) = new ArrayBuilder.ofBoolean()
89+
def apply() = new ArrayBuilder.ofBoolean()
90+
}
91+
92+
private[this] val cbfByteArray = new CanBuildFrom[Array[_], Byte, Array[Byte]] {
93+
def apply(from: Array[_]) = new ArrayBuilder.ofByte()
94+
def apply() = new ArrayBuilder.ofByte()
95+
}
96+
97+
private[this] val cbfCharArray = new CanBuildFrom[Array[_], Char, Array[Char]] {
98+
def apply(from: Array[_]) = new ArrayBuilder.ofChar()
99+
def apply() = new ArrayBuilder.ofChar()
100+
}
101+
102+
private[this] val cbfDoubleArray = new CanBuildFrom[Array[_], Double, Array[Double]] {
103+
def apply(from: Array[_]) = new ArrayBuilder.ofDouble()
104+
def apply() = new ArrayBuilder.ofDouble()
105+
}
106+
107+
private[this] val cbfFloatArray = new CanBuildFrom[Array[_], Float, Array[Float]] {
108+
def apply(from: Array[_]) = new ArrayBuilder.ofFloat()
109+
def apply() = new ArrayBuilder.ofFloat()
110+
}
111+
112+
private[this] val cbfIntArray = new CanBuildFrom[Array[_], Int, Array[Int]] {
113+
def apply(from: Array[_]) = new ArrayBuilder.ofInt()
114+
def apply() = new ArrayBuilder.ofInt()
115+
}
116+
117+
private[this] val cbfLongArray = new CanBuildFrom[Array[_], Long, Array[Long]] {
118+
def apply(from: Array[_]) = new ArrayBuilder.ofLong()
119+
def apply() = new ArrayBuilder.ofLong()
120+
}
121+
122+
private[this] val cbfShortArray = new CanBuildFrom[Array[_], Short, Array[Short]] {
123+
def apply(from: Array[_]) = new ArrayBuilder.ofShort()
124+
def apply() = new ArrayBuilder.ofShort()
125+
}
126+
127+
private[this] val cbfUnitArray = new CanBuildFrom[Array[_], Unit, Array[Unit]] {
128+
def apply(from: Array[_]) = new ArrayBuilder.ofUnit()
129+
def apply() = new ArrayBuilder.ofUnit()
130+
}
131+
132+
private[this] val cbfObjectArray = refCBF[Object]
133+
private[this] def refCBF[T <: AnyRef](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] =
65134
new CanBuildFrom[Array[_], T, Array[T]] {
66-
def apply(from: Array[_]) = ArrayBuilder.make[T]()(t)
67-
def apply() = ArrayBuilder.make[T]()(t)
135+
def apply(from: Array[_]) = new ArrayBuilder.ofRef[T]()(t)
136+
def apply() = new ArrayBuilder.ofRef[T]()(t)
68137
}
69138

70139
/**

library/src/scala/collection/BitSet.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ object BitSet extends BitSetFactory[BitSet] {
3232
def newBuilder = immutable.BitSet.newBuilder
3333

3434
/** $canBuildFromInfo */
35-
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
35+
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = ReusableCBF
36+
private[this] val ReusableCBF = bitsetCanBuildFrom
3637
}
3738

library/src/scala/collection/GenMap.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,8 @@ object GenMap extends GenMapFactory[GenMap] {
3535
def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty
3636

3737
/** $mapCanBuildFromInfo */
38-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), GenMap[K, V]] = new MapCanBuildFrom[K, V]
38+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), GenMap[K, V]] =
39+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), GenMap[K, V]]]
40+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
41+
3942
}

library/src/scala/collection/IterableView.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ package scala
1414
package collection
1515

1616
import generic._
17-
import TraversableView.NoBuilder
17+
import TraversableView.noBuilder
1818

1919
/** A base trait for non-strict views of `Iterable`s.
2020
* $iterableViewInfo
@@ -27,8 +27,9 @@ trait IterableView[+A, +Coll] extends IterableViewLike[A, Coll, IterableView[A,
2727
object IterableView {
2828
type Coll = TraversableView[_, C] forSome {type C <: Traversable[_]}
2929
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IterableView[A, Iterable[_]]] =
30-
new CanBuildFrom[Coll, A, IterableView[A, Iterable[_]]] {
31-
def apply(from: Coll) = new NoBuilder
32-
def apply() = new NoBuilder
30+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, IterableView[A, Iterable[_]]]]
31+
private[this] val ReusableCBF = new CanBuildFrom[Coll, Any, IterableView[Any, Iterable[_]]] {
32+
def apply(from: Coll) = noBuilder[Any]
33+
def apply() = noBuilder
3334
}
3435
}

library/src/scala/collection/Map.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ object Map extends MapFactory[Map] {
4545
def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty
4646

4747
/** $mapCanBuildFromInfo */
48-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
48+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] =
49+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), Map[K, V]]]
50+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
4951

5052
/** An abstract shell used by { mutable, immutable }.Map but not by collection.Map
5153
* because of variance issues.

library/src/scala/collection/SeqView.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ package scala
1414
package collection
1515

1616
import generic._
17-
import TraversableView.NoBuilder
17+
import TraversableView.noBuilder
1818

1919
/** A base trait for non-strict views of sequences.
2020
* $seqViewInfo
@@ -28,8 +28,8 @@ object SeqView {
2828
type Coll = TraversableView[_, C] forSome {type C <: Traversable[_]}
2929
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, SeqView[A, Seq[_]]] =
3030
new CanBuildFrom[Coll, A, SeqView[A, Seq[_]]] {
31-
def apply(from: Coll) = new NoBuilder
32-
def apply() = new NoBuilder
31+
def apply(from: Coll) = noBuilder
32+
def apply() = noBuilder
3333
}
3434
}
3535

library/src/scala/collection/Set.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ trait Set[A] extends (A => Boolean)
4444
object Set extends SetFactory[Set] {
4545
def newBuilder[A] = immutable.Set.newBuilder[A]
4646
override def empty[A]: Set[A] = immutable.Set.empty[A]
47-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
47+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] =
48+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Set[A]]]
49+
private[this] val ReusableCBF = setCanBuildFrom[Any]
4850
}
4951

5052
/** Explicit instantiation of the `Set` trait to reduce class file size in subclasses. */

library/src/scala/collection/TraversableView.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ trait TraversableView[+A, +Coll] extends TraversableViewLike[A, Coll, Traversabl
2525
* `TraversableView`s work. Its definitions are generally not accessed directly by clients.
2626
*/
2727
object TraversableView {
28+
private[this] val reusedNoBuilder = new NoBuilder[Any]
29+
private[collection] def noBuilder[A] = reusedNoBuilder.asInstanceOf[NoBuilder[A]]
30+
//should be private
2831
class NoBuilder[A] extends Builder[A, Nothing] {
2932
def +=(elem: A): this.type = this
3033
def iterator: Iterator[A] = Iterator.empty
@@ -34,7 +37,7 @@ object TraversableView {
3437
type Coll = TraversableView[_, C] forSome {type C <: Traversable[_]}
3538
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, TraversableView[A, Traversable[_]]] =
3639
new CanBuildFrom[Coll, A, TraversableView[A, Traversable[_]]] {
37-
def apply(from: Coll) = new NoBuilder
38-
def apply() = new NoBuilder
40+
def apply(from: Coll) = noBuilder
41+
def apply() = noBuilder
3942
}
4043
}

library/src/scala/collection/concurrent/TrieMap.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,9 @@ extends scala.collection.concurrent.Map[K, V]
970970
object TrieMap extends MutableMapFactory[TrieMap] {
971971
val inodeupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[INodeBase[_, _]], classOf[MainNode[_, _]], "mainnode")
972972

973-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), TrieMap[K, V]] = new MapCanBuildFrom[K, V]
973+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), TrieMap[K, V]] =
974+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), TrieMap[K, V]]]
975+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
974976

975977
def empty[K, V]: TrieMap[K, V] = new TrieMap[K, V]
976978

library/src/scala/collection/immutable/BitSet.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ object BitSet extends BitSetFactory[BitSet] {
8181
}
8282

8383
/** $bitsetCanBuildFrom */
84-
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
84+
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = ReusableCBF
85+
private[this] val ReusableCBF = bitsetCanBuildFrom
8586

8687
/** A bitset containing all the bits in an array */
8788
def fromBitMask(elems: Array[Long]): BitSet = {

library/src/scala/collection/immutable/HashSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ sealed class HashSet[A] extends AbstractSet[A]
213213
object HashSet extends ImmutableSetFactory[HashSet] {
214214

215215
/** $setCanBuildFromInfo */
216-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A]
216+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] =
217+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, HashSet[A]]]
218+
private[this] val ReusableCBF = setCanBuildFrom[Any]
217219

218220
private object EmptyHashSet extends HashSet[Any] {
219221
override def head: Any = throw new NoSuchElementException("Empty Set")

library/src/scala/collection/immutable/IntMap.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ package scala
1414
package collection
1515
package immutable
1616

17-
import scala.collection.generic.{ CanBuildFrom, BitOperations }
18-
import scala.collection.mutable.{ Builder, MapBuilder }
17+
import scala.collection.generic.{BitOperations, CanBuildFrom}
18+
import scala.collection.mutable.{Builder, MapBuilder}
1919
import scala.annotation.tailrec
2020

2121
/** Utility class for integer maps.
@@ -50,9 +50,11 @@ import IntMapUtils._
5050
*/
5151
object IntMap {
5252
/** $mapCanBuildFromInfo */
53-
implicit def canBuildFrom[A, B] = new CanBuildFrom[IntMap[A], (Int, B), IntMap[B]] {
54-
def apply(from: IntMap[A]): Builder[(Int, B), IntMap[B]] = apply()
55-
def apply(): Builder[(Int, B), IntMap[B]] = new MapBuilder[Int, B, IntMap[B]](empty[B])
53+
implicit def canBuildFrom[A, B]: CanBuildFrom[IntMap[A], (Int, B), IntMap[B]] =
54+
ReusableCBF.asInstanceOf[CanBuildFrom[IntMap[A], (Int, B), IntMap[B]]]
55+
private val ReusableCBF = new CanBuildFrom[IntMap[Any], (Int, Any), IntMap[Any]] {
56+
def apply(from: IntMap[Any]): Builder[(Int, Any), IntMap[Any]] = apply()
57+
def apply(): Builder[(Int, Any), IntMap[Any]] = new MapBuilder[Int, Any, IntMap[Any]](empty[Any])
5658
}
5759

5860
def empty[T] : IntMap[T] = IntMap.Nil

library/src/scala/collection/immutable/ListMap.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ object ListMap extends ImmutableMapFactory[ListMap] {
3737
* $mapCanBuildFromInfo
3838
*/
3939
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), ListMap[A, B]] =
40-
new MapCanBuildFrom[A, B]
40+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (A, B), ListMap[A, B]]]
41+
private[this] val ReusableCBF = new MapCanBuildFrom[Any, Any]
4142

4243
def empty[A, B]: ListMap[A, B] = EmptyListMap.asInstanceOf[ListMap[A, B]]
4344

library/src/scala/collection/immutable/ListSet.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ object ListSet extends ImmutableSetFactory[ListSet] {
3434
* $setCanBuildFromInfo
3535
*/
3636
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] =
37-
setCanBuildFrom[A]
37+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, ListSet[A]]]
38+
private[this] val ReusableCBF = setCanBuildFrom[Any]
3839

3940
@SerialVersionUID(5010379588739277132L)
4041
private object EmptyListSet extends ListSet[Any]

library/src/scala/collection/immutable/LongMap.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ import LongMapUtils._
5050
*/
5151
object LongMap {
5252
/** $mapCanBuildFromInfo */
53-
implicit def canBuildFrom[A, B] = new CanBuildFrom[LongMap[A], (Long, B), LongMap[B]] {
54-
def apply(from: LongMap[A]): Builder[(Long, B), LongMap[B]] = apply()
55-
def apply(): Builder[(Long, B), LongMap[B]] = new MapBuilder[Long, B, LongMap[B]](empty[B])
53+
implicit def canBuildFrom[A, B]: CanBuildFrom[LongMap[A], (Long, B), LongMap[B]] =
54+
ReusableCBF.asInstanceOf[CanBuildFrom[LongMap[A], (Long, B), LongMap[B]]]
55+
private[this] val ReusableCBF = new CanBuildFrom[LongMap[Any], (Long, Any), LongMap[Any]] {
56+
def apply(from: LongMap[Any]): Builder[(Long, Any), LongMap[Any]] = apply()
57+
def apply(): Builder[(Long, Any), LongMap[Any]] = new MapBuilder[Long, Any, LongMap[Any]](empty[Any])
5658
}
5759

5860
def empty[T]: LongMap[T] = LongMap.Nil

library/src/scala/collection/immutable/Map.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ trait Map[K, +V] extends Iterable[(K, V)]
8383
object Map extends ImmutableMapFactory[Map] {
8484

8585
/** $mapCanBuildFromInfo */
86-
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
86+
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] =
87+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, (K, V), Map[K, V]]]
88+
private[this] val ReusableCBF = new MapCanBuildFrom[Nothing, Nothing]
8789

8890
def empty[K, V]: Map[K, V] = EmptyMap.asInstanceOf[Map[K, V]]
8991

library/src/scala/collection/immutable/Set.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ trait Set[A] extends Iterable[A]
6464
*/
6565
object Set extends ImmutableSetFactory[Set] {
6666
/** $setCanBuildFromInfo */
67-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
67+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] =
68+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Set[A]]]
69+
private[this] val ReusableCBF = setCanBuildFrom[Any]
6870

6971
/** An optimized representation for immutable empty sets */
7072
@SerialVersionUID(-2443710944435909512L)

library/src/scala/collection/immutable/Stream.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,9 @@ object Stream extends SeqFactory[Stream] {
10871087
*/
10881088
class StreamCanBuildFrom[A] extends GenericCanBuildFrom[A]
10891089

1090-
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Stream[A]] = new StreamCanBuildFrom[A]
1090+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Stream[A]] =
1091+
ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Stream[A]]]
1092+
private[this] val ReusableCBF = new StreamCanBuildFrom[Any]
10911093

10921094
/** Creates a new builder for a stream */
10931095
def newBuilder[A]: Builder[A, Stream[A]] = new StreamBuilder[A]

library/src/scala/collection/immutable/WrappedString.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ final class WrappedString(val self: String) extends AbstractSeq[Char] with Index
5656
* @since 2.8
5757
*/
5858
object WrappedString {
59-
implicit def canBuildFrom: CanBuildFrom[WrappedString, Char, WrappedString] = new CanBuildFrom[WrappedString, Char, WrappedString] {
59+
implicit def canBuildFrom: CanBuildFrom[WrappedString, Char, WrappedString] =
60+
ReusableCBF.asInstanceOf[CanBuildFrom[WrappedString, Char, WrappedString]]
61+
private[this] val ReusableCBF = new CanBuildFrom[WrappedString, Char, WrappedString] {
6062
def apply(from: WrappedString) = newBuilder
6163
def apply() = newBuilder
6264
}

library/src/scala/collection/mutable/AnyRefMap.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,10 +450,11 @@ object AnyRefMap {
450450
private val exceptionDefault = new ExceptionDefault
451451

452452
implicit def canBuildFrom[K <: AnyRef, V, J <: AnyRef, U]: CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] =
453-
new CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] {
454-
def apply(from: AnyRefMap[K,V]): AnyRefMapBuilder[J, U] = apply()
455-
def apply(): AnyRefMapBuilder[J, U] = new AnyRefMapBuilder[J, U]
456-
}
453+
ReusableCBFInstance.asInstanceOf[CanBuildFrom[AnyRefMap[K, V], (J, U), AnyRefMap[J, U]]]
454+
private[this] val ReusableCBFInstance = new CanBuildFrom[AnyRefMap[AnyRef, Any], (AnyRef, Any), AnyRefMap[AnyRef, Any]] {
455+
def apply(from: AnyRefMap[AnyRef, Any]): AnyRefMapBuilder[AnyRef, Any] = apply()
456+
def apply(): AnyRefMapBuilder[AnyRef, Any] = new AnyRefMapBuilder[AnyRef, Any]
457+
}
457458

458459
/** A builder for instances of `AnyRefMap`.
459460
*

library/src/scala/collection/mutable/ArrayBuilder.scala

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,21 @@ object ArrayBuilder {
3737
*/
3838
def make[T: ClassTag](): ArrayBuilder[T] = {
3939
val tag = implicitly[ClassTag[T]]
40-
tag.runtimeClass match {
41-
case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
42-
case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
43-
case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
44-
case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
45-
case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
46-
case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
47-
case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
48-
case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
49-
case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
50-
case _ => new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
40+
val cls = tag.runtimeClass
41+
if (cls.isPrimitive) {
42+
cls match {
43+
case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
44+
case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
45+
case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
46+
case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
47+
case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
48+
case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
49+
case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
50+
case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
51+
case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
52+
}
53+
} else {
54+
new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
5155
}
5256
}
5357

library/src/scala/collection/mutable/BitSet.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ object BitSet extends BitSetFactory[BitSet] {
193193
def newBuilder: Builder[Int, BitSet] = new GrowingBuilder[Int, BitSet](empty)
194194

195195
/** $bitsetCanBuildFrom */
196-
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
196+
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = ReusableCBF
197+
private[this] val ReusableCBF = bitsetCanBuildFrom
197198

198199
/** A bitset containing all the bits in an array */
199200
def fromBitMask(elems: Array[Long]): BitSet = {

0 commit comments

Comments
 (0)