diff options
-rw-r--r-- | src/library/scala/collection/immutable/HashSet.scala | 15 | ||||
-rw-r--r-- | test/files/run/bug408.scala | 12 |
2 files changed, 21 insertions, 6 deletions
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala index 25a8059b0c..2320187be9 100644 --- a/src/library/scala/collection/immutable/HashSet.scala +++ b/src/library/scala/collection/immutable/HashSet.scala @@ -115,17 +115,20 @@ class HashSet[A] extends Set[A] private def makeCopy(last: HashSet[A]) { def undo(m: HashSet[A]) { - if (m ne last) { - undo(m.later) - if (m.deleted) addEntry(m.changedElem) - else removeEntry(m.changedElem) - } + if (m.deleted) addEntry(m.changedElem) + else removeEntry(m.changedElem) } table = new scala.Array[AnyRef](last.table.length) scala.Array.copy(last.table, 0, table, 0, table.length) tableSize = last.tableSize threshold = last.threshold - undo(this) + + // we need to work from the end of the list but non-tail-recursion + // potentially blows the stack, so instead we create a stack on the heap. + // See ticket #408. + val toUndo = new mutable.Stack[HashSet[A]] + toUndo pushAll ((Iterator iterate this)(_.later) takeWhile (_ ne last)) + toUndo foreach undo later = null } diff --git a/test/files/run/bug408.scala b/test/files/run/bug408.scala new file mode 100644 index 0000000000..9e51e881ed --- /dev/null +++ b/test/files/run/bug408.scala @@ -0,0 +1,12 @@ +object Test +{ + val a = scala.collection.immutable.Set.empty ++ (0 to 100000) + val b = scala.collection.immutable.Set.empty ++ (0 to 100000) + + def main(args: Array[String]): Unit = { + a -- b + a -- b + a -- b + a -- b + } +} |