Skip to content

Commit 466821d

Browse files
committed
Merge pull request scala#4648 from Ichoran/issue/8554-again
SI-8554 Two-arg remove now throws exception on overly-large count
2 parents d5f5b26 + 23203f7 commit 466821d

File tree

5 files changed

+35
-23
lines changed

5 files changed

+35
-23
lines changed

src/library/scala/collection/mutable/ArrayBuffer.scala

+8-5
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,16 @@ class ArrayBuffer[A](override protected val initialSize: Int)
149149
/** Removes the element on a given index position. It takes time linear in
150150
* the buffer size.
151151
*
152-
* @param n the index which refers to the first element to delete.
153-
* @param count the number of elements to delete
154-
* @throws IndexOutOfBoundsException if `n` is out of bounds.
152+
* @param n the index which refers to the first element to remove.
153+
* @param count the number of elements to remove.
154+
* @throws IndexOutOfBoundsException if the index `n` is not in the valid range
155+
* `0 <= n <= length - count` (with `count > 0`).
156+
* @throws IllegalArgumentException if `count < 0`.
155157
*/
156158
override def remove(n: Int, count: Int) {
157-
require(count >= 0, "removing negative number of elements")
158-
if (n < 0 || n > size0 - count) throw new IndexOutOfBoundsException(n.toString)
159+
if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
160+
else if (count == 0) return // Did nothing
161+
if (n < 0 || n > size0 - count) throw new IndexOutOfBoundsException("at " + n.toString + " deleting " + count.toString)
159162
copy(n + count, n, size0 - (n + count))
160163
reduceToSize(size0 - count)
161164
}

src/library/scala/collection/mutable/BufferLike.scala

+5-2
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,18 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]]
105105
*/
106106
def remove(n: Int): A
107107

108-
/** Removes a number of elements from a given index position.
108+
/** Removes a number of elements from a given index position. Subclasses of `BufferLike`
109+
* will typically override this method to provide better performance than `count`
110+
* successive calls to single-element `remove`.
109111
*
110112
* @param n the index which refers to the first element to remove.
111113
* @param count the number of elements to remove.
112114
* @throws IndexOutOfBoundsException if the index `n` is not in the valid range
113-
* `0 <= n <= length - count`.
115+
* `0 <= n <= length - count` (with `count > 0`).
114116
* @throws IllegalArgumentException if `count < 0`.
115117
*/
116118
def remove(n: Int, count: Int) {
119+
if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
117120
for (i <- 0 until count) remove(n)
118121
}
119122

src/library/scala/collection/mutable/ListBuffer.scala

+6-5
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,14 @@ final class ListBuffer[A]
262262
*
263263
* @param n the index which refers to the first element to remove.
264264
* @param count the number of elements to remove.
265+
* @throws IndexOutOfBoundsException if the index `n` is not in the valid range
266+
* `0 <= n <= length - count` (with `count > 0`).
267+
* @throws IllegalArgumentException if `count < 0`.
265268
*/
266-
@migration("Invalid input values will be rejected in future releases.", "2.11")
267269
override def remove(n: Int, count: Int) {
268-
if (n >= len)
269-
return
270-
if (count < 0)
271-
throw new IllegalArgumentException(s"removing negative number ($count) of elements")
270+
if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
271+
else if (count == 0) return // Nothing to do
272+
if (n < 0 || n > len - count) throw new IndexOutOfBoundsException("at " + n.toString + " deleting " + count.toString)
272273
if (exported) copy()
273274
val n1 = n max 0
274275
val count1 = count min (len - n1)

test/files/run/t6634.check

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,31 @@ String OK.
44
Length OK.
55

66
Trying lb1 ...
7+
java.lang.IndexOutOfBoundsException: at 6 deleting 6
78
Checking ...
89
String OK.
910
Length OK.
1011

1112
Trying lb2 ...
13+
java.lang.IndexOutOfBoundsException: at 99 deleting 6
1214
Checking ...
1315
String OK.
1416
Length OK.
1517

1618
Trying lb3 ...
19+
java.lang.IndexOutOfBoundsException: at 1 deleting 9
1720
Checking ...
1821
String OK.
1922
Length OK.
2023

2124
Trying lb4 ...
25+
java.lang.IndexOutOfBoundsException: at -1 deleting 1
2226
Checking ...
2327
String OK.
2428
Length OK.
2529

2630
Trying lb5 ...
27-
java.lang.IllegalArgumentException: removing negative number (-1) of elements
31+
java.lang.IllegalArgumentException: removing negative number of elements: -1
2832
Checking ...
2933
String OK.
3034
Length OK.

test/files/run/t6634.scala

+11-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ object Test extends App {
88
try {
99
lb0.remove(5, 0)
1010
} catch {
11-
// Not thrown in 2.10, will be thrown in 2.11
11+
// Should not be thrown--nothing is deleted so nothing to do
1212
case ex: IndexOutOfBoundsException => println(ex)
1313
}
1414
checkNotCorrupted(lb0)
@@ -17,8 +17,8 @@ object Test extends App {
1717
println("Trying lb1 ...")
1818
try {
1919
lb1.remove(6, 6)
20-
} catch {
21-
// Not thrown in 2.10, will be thrown in 2.11
20+
} catch {
21+
// Not thrown in 2.11, is thrown in 2.12
2222
case ex: IndexOutOfBoundsException => println(ex)
2323
}
2424
checkNotCorrupted(lb1)
@@ -28,7 +28,7 @@ object Test extends App {
2828
try {
2929
lb2.remove(99, 6)
3030
} catch {
31-
// Not thrown in 2.10, will be thrown in 2.11
31+
// Not thrown in 2.11, is thrown in 2.12
3232
case ex: IndexOutOfBoundsException => println(ex)
3333
}
3434
checkNotCorrupted(lb2)
@@ -38,26 +38,27 @@ object Test extends App {
3838
try {
3939
lb3.remove(1, 9)
4040
} catch {
41-
// Not thrown in 2.10, will be thrown in 2.11
42-
case ex: IllegalArgumentException => println(ex)
41+
// Not thrown in 2.11, is thrown in 2.12
42+
case ex: IndexOutOfBoundsException => println(ex)
4343
}
44-
checkNotCorrupted(lb3, "ListBuffer('a)", 1)
44+
checkNotCorrupted(lb3)
4545

4646
val lb4 = newLB
4747
println("Trying lb4 ...")
4848
try {
4949
lb4.remove(-1, 1)
5050
} catch {
51-
// Not thrown in 2.10, will be thrown in 2.11
51+
// Not thrown in 2.11, is thrown in 2.12
5252
case ex: IndexOutOfBoundsException => println(ex)
5353
}
54-
checkNotCorrupted(lb4, "ListBuffer('b, 'c, 'd, 'e)", 4)
54+
checkNotCorrupted(lb4)
5555

5656
val lb5 = newLB
5757
println("Trying lb5 ...")
5858
try {
5959
lb5.remove(1, -1)
6060
} catch {
61+
// Was thrown prior to 2.12 also
6162
case ex: IllegalArgumentException => println(ex)
6263
}
6364
checkNotCorrupted(lb5)
@@ -77,4 +78,4 @@ object Test extends App {
7778
else println("!!! length FAILED: " + len)
7879
println()
7980
}
80-
}
81+
}

0 commit comments

Comments
 (0)