summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-06-04 18:34:02 +0000
committerPaul Phillips <paulp@improving.org>2010-06-04 18:34:02 +0000
commitda5910c7c622fc248fe525f5c03b1dee6be384b5 (patch)
tree966214d469ea0ecbd0370b18ab96af1d211a9af1
parent245ec93fb132d2597a05d7ae9e081cd1adf356a3 (diff)
downloadscala-da5910c7c622fc248fe525f5c03b1dee6be384b5.tar.gz
scala-da5910c7c622fc248fe525f5c03b1dee6be384b5.tar.bz2
scala-da5910c7c622fc248fe525f5c03b1dee6be384b5.zip
Fix for init-order caused NPE in NumericRange.
ran across some tortured logic trying to accomodate the long abandoned idea of having 5 != 5L, so simplified the contains method. Closes #3518, no review.
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala45
-rw-r--r--test/files/run/bug3518.scala16
2 files changed, 33 insertions, 28 deletions
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index db44e9ffa0..b8bd5bd20e 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -40,8 +40,8 @@ import generic._
abstract class NumericRange[T]
(val start: T, val end: T, val step: T, val isInclusive: Boolean)
(implicit num: Integral[T])
-extends IndexedSeq[T]
-{
+extends IndexedSeq[T] {
+
/** Note that NumericRange must be invariant so that constructs
* such as
*
@@ -122,18 +122,6 @@ extends IndexedSeq[T]
else start + (fromInt(idx) * step)
}
- // a well-typed contains method.
- def containsTyped(x: T): Boolean = {
- def divides(d: T, by: T) = equiv(d % by, zero)
-
- limitTest(x) || (
- if (step > zero)
- (start <= x) && (x < end) && divides(x - start, step)
- else
- (start >= x) && (x > end) && divides(start - x, step)
- )
- }
-
// Motivated by the desire for Double ranges with BigDecimal precision,
// we need some way to map a Range and get another Range. This can't be
// done in any fully general way because Ranges are not arbitrary
@@ -165,7 +153,7 @@ extends IndexedSeq[T]
if (isInclusive) NumericRange.inclusive(start, end, step)
else NumericRange(start, end, step)
- private val underlyingRange: NumericRange[T] = self
+ private lazy val underlyingRange: NumericRange[T] = self
override def foreach[U](f: A => U) { underlyingRange foreach (x => f(fm(x))) }
override def isEmpty = underlyingRange.isEmpty
override def apply(idx: Int): A = fm(underlyingRange(idx))
@@ -173,20 +161,21 @@ extends IndexedSeq[T]
}
}
- // The contains situation makes for some interesting code.
- // I am not aware of any way to avoid a cast somewhere, because
- // contains must take an Any.
+ // a well-typed contains method.
+ def containsTyped(x: T): Boolean = {
+ def divides(d: T, by: T) = equiv(d % by, zero)
+
+ limitTest(x) || (
+ if (step > zero)
+ (start <= x) && (x < end) && divides(x - start, step)
+ else
+ (start >= x) && (x > end) && divides(start - x, step)
+ )
+ }
+
override def contains(x: Any): Boolean =
- try {
- // if we don't verify that x == typedX, then a range
- // of e.g. Longs will appear to contain an Int because
- // the cast will perform the conversion. (As of this writing
- // it is anticipated that in scala 2.8, 5L != 5 although
- // this is not yet implemented.)
- val typedX = x.asInstanceOf[T]
- containsTyped(typedX) && (x == typedX)
- }
- catch { case _: ClassCastException => super.contains(x) }
+ try containsTyped(x.asInstanceOf[T])
+ catch { case _: ClassCastException => false }
override lazy val hashCode = super.hashCode()
override def equals(other: Any) = other match {
diff --git a/test/files/run/bug3518.scala b/test/files/run/bug3518.scala
new file mode 100644
index 0000000000..033cc19548
--- /dev/null
+++ b/test/files/run/bug3518.scala
@@ -0,0 +1,16 @@
+object Test {
+ val r1 = 1.0 to 10.0 by 0.5
+ val r2 = 1.0 to 1.0 by 1.0
+ val r3 = 10.0 to 1.0 by -0.5
+ val r4 = 1.0 until 1.0 by 1.0
+ val r5 = 1 to 100 by 2
+
+ def main(args: Array[String]): Unit = {
+ assert(r3 forall (r1 contains _))
+ assert(r1 forall (r3 contains _))
+ assert(r2.size == 1)
+ assert(r4.isEmpty)
+ assert(List(1,3,5,97,99) forall (r5 contains _))
+ assert(List(2,4,6,98,100) forall (x => !r5.contains(x)))
+ }
+}