diff options
author | Erik Osheim <d_m@plastic-idolatry.com> | 2013-12-24 15:52:17 -0500 |
---|---|---|
committer | Erik Osheim <d_m@plastic-idolatry.com> | 2013-12-24 15:58:50 -0500 |
commit | 2477bbd9d64df3dbfac063e1fc71115daf0f3ea7 (patch) | |
tree | b0dc9f7b266fd4746ddc4eb8393bcf55f7562cb7 /src/library/scala/collection/immutable/Stream.scala | |
parent | 9f0594c57716ed551918e15be6da843982e8ba12 (diff) | |
download | scala-2477bbd9d64df3dbfac063e1fc71115daf0f3ea7.tar.gz scala-2477bbd9d64df3dbfac063e1fc71115daf0f3ea7.tar.bz2 scala-2477bbd9d64df3dbfac063e1fc71115daf0f3ea7.zip |
SI-8100 - prevent possible SOE during Stream#flatten.
This commit changes stream flatten to avoid allocating a
stack frame for every stream item. Previously, flattening
a stream whose elements are mostly empty would result in
a StackOverflowException.
This commit also adds a test demonstrating the problem.
Diffstat (limited to 'src/library/scala/collection/immutable/Stream.scala')
-rw-r--r-- | src/library/scala/collection/immutable/Stream.scala | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 5e1de44749..e6e4d6ec18 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -960,14 +960,16 @@ self => * }}} */ override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): Stream[B] = { - def flatten1(t: Traversable[B]): Stream[B] = - if (!t.isEmpty) - cons(t.head, flatten1(t.tail)) - else - tail.flatten - - if (isEmpty) Stream.empty - else flatten1(asTraversable(head).seq.toTraversable) + var st: Stream[A] = this + while (st.nonEmpty) { + val h = asTraversable(st.head) + if (h.isEmpty) { + st = st.tail + } else { + return h.toStream #::: st.tail.flatten + } + } + Stream.empty } override def view = new StreamView[A, Stream[A]] { |