Skip to content

Commit

Permalink
SI-6457 ImmutableSetFactory.empty results in StackOverflowError
Browse files Browse the repository at this point in the history
ImmutableSetFactory relies upon empty to create its builder, which in turn relies upon its builder to create an empty.  Added an emptyInstance method to hold the actual empty set (which also removes duplicated functionality for empty sets).

No test, as the original pattern:

  object Factory extends collection.generic.ImmutableSetFactory[collection.immutable.Set] {}

no longer compiles.  This should be verified by whoever checks this commit, but this kind of change is hard to revert by accident.  No reason to waste resources checking it forevermore.
  • Loading branch information
Ichoran committed Jan 15, 2014
1 parent dd87581 commit bfa7031
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 6 deletions.
Expand Up @@ -15,6 +15,7 @@ import scala.language.higherKinds

abstract class ImmutableSetFactory[CC[X] <: immutable.Set[X] with SetLike[X, CC[X]]]
extends SetFactory[CC] {

private[collection] def emptyInstance: CC[Any]
override def empty[A] = emptyInstance.asInstanceOf[CC[A]]
def newBuilder[A]: Builder[A, CC[A]] = new SetBuilder[A, CC[A]](empty[A])
}
4 changes: 2 additions & 2 deletions src/library/scala/collection/immutable/HashSet.scala
Expand Up @@ -99,10 +99,10 @@ object HashSet extends ImmutableSetFactory[HashSet] {

/** $setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A]
override def empty[A]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]]

private object EmptyHashSet extends HashSet[Any] { }

private[collection] def emptyInstance: HashSet[Any] = EmptyHashSet

// utility method to create a HashTrieSet from two leaf HashSets (HashSet1 or HashSetCollision1) with non-colliding hash code)
private def makeHashTrieSet[A](hash0:Int, elem0:HashSet[A], hash1:Int, elem1:HashSet[A], level:Int) : HashTrieSet[A] = {
val index0 = (hash0 >>> level) & 0x1f
Expand Down
3 changes: 2 additions & 1 deletion src/library/scala/collection/immutable/ListSet.scala
Expand Up @@ -22,10 +22,11 @@ import mutable.{ ListBuffer, Builder }
object ListSet extends ImmutableSetFactory[ListSet] {
/** setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] = setCanBuildFrom[A]
override def empty[A] = EmptyListSet.asInstanceOf[ListSet[A]]

override def newBuilder[A]: Builder[A, ListSet[A]] = new ListSetBuilder[A]

private object EmptyListSet extends ListSet[Any] { }
private[collection] def emptyInstance: ListSet[Any] = EmptyListSet

/** A custom builder because forgetfully adding elements one at
* a time to a list backed set puts the "squared" in N^2. There is a
Expand Down
4 changes: 2 additions & 2 deletions src/library/scala/collection/immutable/Set.scala
Expand Up @@ -53,8 +53,7 @@ trait Set[A] extends Iterable[A]
object Set extends ImmutableSetFactory[Set] {
/** $setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
override def empty[A]: Set[A] = EmptySet.asInstanceOf[Set[A]]


/** An optimized representation for immutable empty sets */
private object EmptySet extends AbstractSet[Any] with Set[Any] with Serializable {
override def size: Int = 0
Expand All @@ -64,6 +63,7 @@ object Set extends ImmutableSetFactory[Set] {
def iterator: Iterator[Any] = Iterator.empty
override def foreach[U](f: Any => U): Unit = {}
}
private[collection] def emptyInstance: Set[Any] = EmptySet

/** An optimized representation for immutable sets of size 1 */
@SerialVersionUID(1233385750652442003L)
Expand Down

0 comments on commit bfa7031

Please sign in to comment.