Skip to content

Commit d5cf2d8

Browse files
authored
Merge pull request scala/scala#10928 from JD557/extract-ioob-message
Extract common IndexOutOfBoundsException error message
2 parents dff2675 + f31a7c4 commit d5cf2d8

File tree

12 files changed

+73
-25
lines changed

12 files changed

+73
-25
lines changed

library/src/scala/collection/ArrayOps.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import scala.Predef.{ // unimport all array-related implicit conversions to avoi
4444
_
4545
}
4646
import scala.collection.Stepper.EfficientSplit
47+
import scala.collection.generic.CommonErrors
4748
import scala.collection.immutable.Range
4849
import scala.collection.mutable.ArrayBuilder
4950
import scala.math.Ordering
@@ -1545,7 +1546,8 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal {
15451546
* @throws IndexOutOfBoundsException if `index` does not satisfy `0 <= index < length`.
15461547
*/
15471548
def updated[B >: A : ClassTag](index: Int, elem: B): Array[B] = {
1548-
if(index < 0 || index >= xs.length) throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${xs.length-1})")
1549+
if(index < 0 || index >= xs.length)
1550+
throw CommonErrors.indexOutOfBounds(index = index, max = xs.length-1)
15491551
val dest = toArray[B]
15501552
dest(index) = elem
15511553
dest

library/src/scala/collection/SeqView.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package scala
1414
package collection
1515

1616
import scala.annotation.nowarn
17+
import scala.collection.generic.CommonErrors
1718

1819

1920
trait SeqView[+A] extends SeqOps[A, View, View[A]] with View[A] {
@@ -95,7 +96,10 @@ object SeqView {
9596
def apply(idx: Int): A = if (idx < n) {
9697
underlying(idx)
9798
} else {
98-
throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${if (underlying.knownSize >= 0) knownSize - 1 else "unknown"})")
99+
throw (
100+
if (underlying.knownSize >= 0) CommonErrors.indexOutOfBounds(index = idx, max = knownSize - 1)
101+
else CommonErrors.indexOutOfBounds(index = idx)
102+
)
99103
}
100104
def length: Int = underlying.length min normN
101105
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection
14+
package generic
15+
16+
17+
/** Some precomputed common errors to reduce the generated code size.
18+
*/
19+
private[collection] object CommonErrors {
20+
/** IndexOutOfBounds exception with a known max index */
21+
@noinline
22+
def indexOutOfBounds(index: Int, max: Int): IndexOutOfBoundsException =
23+
new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${max})")
24+
25+
/** IndexOutOfBounds exception with an unknown max index. */
26+
@noinline
27+
def indexOutOfBounds(index: Int): IndexOutOfBoundsException =
28+
new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max unknown)")
29+
}

library/src/scala/collection/immutable/List.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ package immutable
1717
import scala.annotation.unchecked.uncheckedVariance
1818
import scala.annotation.tailrec
1919
import mutable.{Builder, ListBuffer}
20-
import scala.collection.generic.DefaultSerializable
20+
import scala.collection.generic.{CommonErrors, DefaultSerializable}
2121
import scala.runtime.Statics.releaseFence
2222

2323
/** A class for immutable linked lists representing ordered collections
@@ -238,7 +238,7 @@ sealed abstract class List[+A]
238238
if (i == index && current.nonEmpty) {
239239
prefix.prependToList(elem :: current.tail)
240240
} else {
241-
throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${length-1})")
241+
throw CommonErrors.indexOutOfBounds(index = index, max = length - 1)
242242
}
243243
}
244244

library/src/scala/collection/immutable/NumericRange.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package scala.collection.immutable
1414

1515
import scala.collection.Stepper.EfficientSplit
1616
import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape}
17+
import scala.collection.generic.CommonErrors
1718

1819
/** `NumericRange` is a more generic version of the
1920
* `Range` class which works with arbitrary types.
@@ -104,7 +105,8 @@ sealed class NumericRange[T](
104105

105106
@throws[IndexOutOfBoundsException]
106107
def apply(idx: Int): T = {
107-
if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${length - 1})")
108+
if (idx < 0 || idx >= length)
109+
throw CommonErrors.indexOutOfBounds(index = idx, max = length - 1)
108110
else locationAfterN(idx)
109111
}
110112

library/src/scala/collection/immutable/Range.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package collection.immutable
1515

1616
import scala.collection.Stepper.EfficientSplit
1717
import scala.collection.convert.impl.RangeStepper
18+
import scala.collection.generic.CommonErrors
1819
import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape}
1920
import scala.util.hashing.MurmurHash3
2021

@@ -177,7 +178,8 @@ sealed abstract class Range(
177178
@throws[IndexOutOfBoundsException]
178179
final def apply(idx: Int): Int = {
179180
validateMaxLength()
180-
if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${numRangeElements-1})")
181+
if (idx < 0 || idx >= numRangeElements)
182+
throw CommonErrors.indexOutOfBounds(index = idx, max = numRangeElements - 1)
181183
else start + (step * idx)
182184
}
183185

library/src/scala/collection/immutable/StrictOptimizedSeqOps.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ package scala
1414
package collection
1515
package immutable
1616

17+
import scala.collection.generic.CommonErrors
18+
1719
/** Trait that overrides operations to take advantage of strict builders.
1820
*/
1921
trait StrictOptimizedSeqOps[+A, +CC[_], +C]
@@ -38,7 +40,11 @@ trait StrictOptimizedSeqOps[+A, +CC[_], +C]
3840
}
3941

4042
override def updated[B >: A](index: Int, elem: B): CC[B] = {
41-
if (index < 0) throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${if (knownSize>=0) knownSize else "unknown"})")
43+
if (index < 0)
44+
throw (
45+
if (knownSize >= 0) CommonErrors.indexOutOfBounds(index = index, max = knownSize)
46+
else CommonErrors.indexOutOfBounds(index = index)
47+
)
4248
val b = iterableFactory.newBuilder[B]
4349
b.sizeHint(this)
4450
var i = 0
@@ -47,7 +53,8 @@ trait StrictOptimizedSeqOps[+A, +CC[_], +C]
4753
b += it.next()
4854
i += 1
4955
}
50-
if (!it.hasNext) throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${i-1})")
56+
if (!it.hasNext)
57+
throw CommonErrors.indexOutOfBounds(index = index, max = i - 1)
5158
b += elem
5259
it.next()
5360
while (it.hasNext) b += it.next()

library/src/scala/collection/immutable/Vector.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import java.util.{Arrays, Spliterator}
2020
import scala.annotation.switch
2121
import scala.annotation.unchecked.uncheckedVariance
2222
import scala.collection.Stepper.EfficientSplit
23-
import scala.collection.generic.DefaultSerializable
23+
import scala.collection.generic.{CommonErrors, DefaultSerializable}
2424
import scala.collection.immutable.VectorInline._
2525
import scala.collection.immutable.VectorStatics._
2626
import scala.collection.mutable.ReusableBuilder
@@ -283,7 +283,7 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va
283283
}
284284

285285
protected[this] def ioob(index: Int): IndexOutOfBoundsException =
286-
new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${length-1})")
286+
CommonErrors.indexOutOfBounds(index = index, max = length - 1)
287287

288288
override final def head: A =
289289
if (prefix1.length == 0) throw new NoSuchElementException("empty.head")

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ package mutable
1717
import java.util.Arrays
1818
import scala.annotation.{nowarn, tailrec}
1919
import scala.collection.Stepper.EfficientSplit
20-
import scala.collection.generic.DefaultSerializable
20+
import scala.collection.generic.{CommonErrors, DefaultSerializable}
2121
import scala.runtime.PStatics.VM_MaxArraySize
2222

2323
/** An implementation of the `Buffer` class using an array to
@@ -99,8 +99,8 @@ class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int)
9999
array = ArrayBuffer.downsize(array, requiredLength)
100100

101101
@inline private def checkWithinBounds(lo: Int, hi: Int) = {
102-
if (lo < 0) throw new IndexOutOfBoundsException(s"$lo is out of bounds (min 0, max ${size0 - 1})")
103-
if (hi > size0) throw new IndexOutOfBoundsException(s"${hi - 1} is out of bounds (min 0, max ${size0 - 1})")
102+
if (lo < 0) throw CommonErrors.indexOutOfBounds(index = lo, max = size0 - 1)
103+
if (hi > size0) throw CommonErrors.indexOutOfBounds(index = hi - 1, max = size0 - 1)
104104
}
105105

106106
def apply(n: Int): A = {

library/src/scala/collection/mutable/ArrayDeque.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package mutable
1616

1717
import scala.annotation.nowarn
1818
import scala.collection.Stepper.EfficientSplit
19-
import scala.collection.generic.DefaultSerializable
19+
import scala.collection.generic.{CommonErrors, DefaultSerializable}
2020
import scala.reflect.ClassTag
2121

2222
/** An implementation of a double-ended queue that internally uses a resizable circular buffer.
@@ -580,7 +580,8 @@ trait ArrayDequeOps[A, +CC[_], +C <: AnyRef] extends StrictOptimizedSeqOps[A, CC
580580
protected def start_+(idx: Int): Int
581581

582582
@inline protected final def requireBounds(idx: Int, until: Int = length): Unit =
583-
if (idx < 0 || idx >= until) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${until-1})")
583+
if (idx < 0 || idx >= until)
584+
throw CommonErrors.indexOutOfBounds(index = idx, max = until - 1)
584585

585586
/**
586587
* This is a more general version of copyToArray - this also accepts a srcStart unlike copyToArray

0 commit comments

Comments
 (0)