diff options
author | Paul Phillips <paulp@improving.org> | 2010-06-07 23:43:14 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-06-07 23:43:14 +0000 |
commit | caa6bf0e7a9c02b7519549c289f7a455bad281b1 (patch) | |
tree | ddd2a4da3fe7969776a039f8ccc44dd6aa2d4292 | |
parent | d6896c490acea8617247cf593060fa67ed82c79c (diff) | |
download | scala-caa6bf0e7a9c02b7519549c289f7a455bad281b1.tar.gz scala-caa6bf0e7a9c02b7519549c289f7a455bad281b1.tar.bz2 scala-caa6bf0e7a9c02b7519549c289f7a455bad281b1.zip |
Most of the iterate implementations were callin...
Most of the iterate implementations were calling the given function one
too many times, leading to tragic failure if the function could not
handle this (such as repeatedly applying tail.) Closes #3540, review by
prokopec.
-rw-r--r-- | src/library/scala/Array.scala | 17 | ||||
-rw-r--r-- | src/library/scala/collection/generic/TraversableFactory.scala | 16 | ||||
-rw-r--r-- | test/files/run/bug3540.scala | 7 |
3 files changed, 28 insertions, 12 deletions
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 9712990d73..250fd09602 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -363,13 +363,18 @@ object Array extends FallbackArrayBuilding { */ def iterate[T: ClassManifest](start: T, len: Int)(f: T => T): Array[T] = { val b = newBuilder[T] - b.sizeHint(len) - var acc = start - var i = 0 - while (i < len) { + + if (len > 0) { + b.sizeHint(len) + var acc = start + var i = 1 b += acc - acc = f(acc) - i += 1 + + while (i < len) { + acc = f(acc) + i += 1 + b += acc + } } b.result } diff --git a/src/library/scala/collection/generic/TraversableFactory.scala b/src/library/scala/collection/generic/TraversableFactory.scala index d8541d2714..c6f5ce4dde 100644 --- a/src/library/scala/collection/generic/TraversableFactory.scala +++ b/src/library/scala/collection/generic/TraversableFactory.scala @@ -224,13 +224,17 @@ abstract class TraversableFactory[CC[X] <: Traversable[X] with GenericTraversabl */ def iterate[A](start: A, len: Int)(f: A => A): CC[A] = { val b = newBuilder[A] - b.sizeHint(len) - var acc = start - var i = 0 - while (i < len) { + if (len > 0) { + b.sizeHint(len) + var acc = start + var i = 1 b += acc - acc = f(acc) - i += 1 + + while (i < len) { + acc = f(acc) + i += 1 + b += acc + } } b.result } diff --git a/test/files/run/bug3540.scala b/test/files/run/bug3540.scala new file mode 100644 index 0000000000..5ffacb5dff --- /dev/null +++ b/test/files/run/bug3540.scala @@ -0,0 +1,7 @@ +object Test { + def main(args: Array[String]): Unit = { + assert(List.iterate(List(1,2,3), 4)(_.tail).last.isEmpty) + assert(Stream.iterate(Stream(1,2,3), 4)(_.tail).last.isEmpty) + assert(Array.iterate(Array(1,2,3), 4)(_.tail).last.isEmpty) + } +} |