From 00a648bc909f794d91570fb962fc7d7fcd055bc5 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 8 May 2012 21:16:33 +0200 Subject: fix SI-1247: don't create a thunk for a by-name argument if the argument expression is a Function0 application --- test/files/run/t1247.check | 1 + test/files/run/t1247.scala | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 test/files/run/t1247.check create mode 100644 test/files/run/t1247.scala (limited to 'test/files') diff --git a/test/files/run/t1247.check b/test/files/run/t1247.check new file mode 100644 index 0000000000..ce123032fd --- /dev/null +++ b/test/files/run/t1247.check @@ -0,0 +1 @@ +Is same closure class: true is same closure: true diff --git a/test/files/run/t1247.scala b/test/files/run/t1247.scala new file mode 100644 index 0000000000..c709b73bc8 --- /dev/null +++ b/test/files/run/t1247.scala @@ -0,0 +1,11 @@ +object Test extends App { + val f = () => 5 + def test(g: => Int) { + val gFunc = g _ + val isSameClosureClass = gFunc.getClass == f.getClass + val isSame = gFunc eq f + println("Is same closure class: "+isSameClosureClass+" is same closure: "+isSame) + } + + test(f()) +} -- cgit v1.2.3 From 83d815622e3e76083496cffa9efb1e7c8fc3e5d3 Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Tue, 8 May 2012 15:51:52 -0400 Subject: Added tests for SI-4190. --- test/files/run/t4190.check | 3 +++ test/files/run/t4190.scala | 6 ++++++ 2 files changed, 9 insertions(+) create mode 100644 test/files/run/t4190.check create mode 100644 test/files/run/t4190.scala (limited to 'test/files') diff --git a/test/files/run/t4190.check b/test/files/run/t4190.check new file mode 100644 index 0000000000..b8aae0c7a1 --- /dev/null +++ b/test/files/run/t4190.check @@ -0,0 +1,3 @@ +a0 +b0 +c0 diff --git a/test/files/run/t4190.scala b/test/files/run/t4190.scala new file mode 100644 index 0000000000..aa88b8708d --- /dev/null +++ b/test/files/run/t4190.scala @@ -0,0 +1,6 @@ +import collection.mutable._ + +object Test extends App { + val x: ArrayBuffer[String] = ArrayBuffer("a", "b", "c") + x.view map (_ + "0") foreach println +} -- cgit v1.2.3 From 58bb2d1bd2000ac3aa2c64b6c5dc56c91e911860 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 8 May 2012 16:02:48 -0700 Subject: Fix for ## inconsistency. Hopefully without slowing things down overmuch. Closes SI-5640. --- src/library/scala/runtime/ScalaRunTime.scala | 11 +++++++---- test/files/run/hashhash.scala | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'test/files') diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 4c5e0e408b..a04fd23710 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -234,10 +234,13 @@ object ScalaRunTime { // Note that these are the implementations called by ##, so they // must not call ## themselves. - @inline def hash(x: Any): Int = - if (x == null) 0 - else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number]) - else x.hashCode + @inline def hash(x: Any): Int = x match { + case null => 0 + case x: Double => hash(x) + case x: Float => hash(x) + case x: java.lang.Number => hash(x) + case _ => x.hashCode + } @inline def hash(dv: Double): Int = { val iv = dv.toInt diff --git a/test/files/run/hashhash.scala b/test/files/run/hashhash.scala index b9cec99a12..dc31df8cfa 100644 --- a/test/files/run/hashhash.scala +++ b/test/files/run/hashhash.scala @@ -6,5 +6,10 @@ object Test { /** Just a little sanity check, not to be confused with a unit test. */ List(5, 5.5f, "abc", new AnyRef, ()) foreach confirmSame List(5.0f, 1.0d, -(5.0f), (-1.0d)) foreach confirmDifferent + + val x = (BigInt(1) << 64).toDouble + val y: Any = x + + assert(x.## == y.##, ((x, y))) } } -- cgit v1.2.3 From 84764949e299329e476824c96fb250f72506bacd Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Tue, 8 May 2012 21:53:25 -0400 Subject: Fixes SI-5328. Iterator.patched failed when from=0. It turns out iterator.patched forgot to drop replacement values if they were at the beginning. This is because the index was advancing before checking to see if replaced elements should be dropped. Moved this behavior to the beginning of next. --- src/library/scala/collection/Iterator.scala | 3 ++- test/files/run/t5328.check | 3 +++ test/files/run/t5328.scala | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t5328.check create mode 100644 test/files/run/t5328.scala (limited to 'test/files') diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index e9a7906527..7d5cd9989c 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -1079,11 +1079,12 @@ trait Iterator[+A] extends TraversableOnce[A] { if (i < from) origElems.hasNext else patchElems.hasNext || origElems.hasNext def next(): B = { + // We have to do this *first* just in case from = 0. + if (i == from) origElems = origElems drop replaced val result: B = if (i < from || !patchElems.hasNext) origElems.next() else patchElems.next() i += 1 - if (i == from) origElems = origElems drop replaced result } } diff --git a/test/files/run/t5328.check b/test/files/run/t5328.check new file mode 100644 index 0000000000..77a43968c5 --- /dev/null +++ b/test/files/run/t5328.check @@ -0,0 +1,3 @@ +2 +1,2,8 +1,8,3 diff --git a/test/files/run/t5328.scala b/test/files/run/t5328.scala new file mode 100644 index 0000000000..12adf45b84 --- /dev/null +++ b/test/files/run/t5328.scala @@ -0,0 +1,5 @@ +object Test extends App { + println(Vector(1).view.updated(0,2).toList mkString ",") + println(Seq(1,2,3).view.updated(2,8).toList mkString ",") + println(List(1,2,3).view.updated(1,8).toList mkString ",") +} -- cgit v1.2.3 From b5919100e785df58bde35bb24abe9d60b4da08a2 Mon Sep 17 00:00:00 2001 From: Dominik Gruntz Date: Wed, 9 May 2012 15:01:25 +0200 Subject: removes redundant hash implementation from BoxesRunTime.java --- src/library/scala/runtime/BoxesRunTime.java | 61 ---------------------------- src/library/scala/runtime/ScalaRunTime.scala | 30 +++++++++++++- test/files/run/hashCodeBoxesRunTime.scala | 28 ------------- test/files/run/hashCodeScalaRunTime.scala | 28 +++++++++++++ test/files/run/hashhash.scala | 8 ++++ 5 files changed, 64 insertions(+), 91 deletions(-) delete mode 100644 test/files/run/hashCodeBoxesRunTime.scala create mode 100644 test/files/run/hashCodeScalaRunTime.scala (limited to 'test/files') diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index 258a176671..0df196b2a6 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -203,67 +203,6 @@ public final class BoxesRunTime } } - /** Hashcode algorithm is driven by the requirements imposed - * by primitive equality semantics, namely that equal objects - * have equal hashCodes. The first priority are the integral/char - * types, which already have the same hashCodes for the same - * values except for Long. So Long's hashCode is altered to - * conform to Int's for all values in Int's range. - * - * Float is problematic because it's far too small to hold - * all the Ints, so for instance Int.MaxValue.toFloat claims - * to be == to each of the largest 64 Ints. There is no way - * to preserve equals/hashCode alignment without compromising - * the hashCode distribution, so Floats are only guaranteed - * to have the same hashCode for whole Floats in the range - * Short.MinValue to Short.MaxValue (2^16 total.) - * - * Double has its hashCode altered to match the entire Int range, - * but is not guaranteed beyond that. (But could/should it be? - * The hashCode is only 32 bits so this is a more tractable - * issue than Float's, but it might be better simply to exclude it.) - * - * Note: BigInt and BigDecimal, being arbitrary precision, could - * be made consistent with all other types for the Int range, but - * as yet have not. - * - * Note: Among primitives, Float.NaN != Float.NaN, but the boxed - * verisons are equal. This still needs reconciliation. - */ - public static int hashFromLong(java.lang.Long n) { - int iv = n.intValue(); - if (iv == n.longValue()) return iv; - else return n.hashCode(); - } - public static int hashFromDouble(java.lang.Double n) { - int iv = n.intValue(); - double dv = n.doubleValue(); - if (iv == dv) return iv; - - long lv = n.longValue(); - if (lv == dv) return java.lang.Long.valueOf(lv).hashCode(); - else return n.hashCode(); - } - public static int hashFromFloat(java.lang.Float n) { - int iv = n.intValue(); - float fv = n.floatValue(); - if (iv == fv) return iv; - - long lv = n.longValue(); - if (lv == fv) return java.lang.Long.valueOf(lv).hashCode(); - else return n.hashCode(); - } - public static int hashFromNumber(java.lang.Number n) { - if (n instanceof java.lang.Long) return hashFromLong((java.lang.Long)n); - else if (n instanceof java.lang.Double) return hashFromDouble((java.lang.Double)n); - else if (n instanceof java.lang.Float) return hashFromFloat((java.lang.Float)n); - else return n.hashCode(); - } - public static int hashFromObject(Object a) { - if (a instanceof Number) return hashFromNumber((Number)a); - else return a.hashCode(); - } - private static int unboxCharOrInt(Object arg1, int code) { if (code == CHAR) return ((java.lang.Character) arg1).charValue(); diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index a04fd23710..b3d99aa8d8 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -233,12 +233,39 @@ object ScalaRunTime { // // Note that these are the implementations called by ##, so they // must not call ## themselves. + // + // Hashcode algorithm is driven by the requirements imposed + // by primitive equality semantics, namely that equal objects + // have equal hashCodes. The first priority are the integral/char + // types, which already have the same hashCodes for the same + // values except for Long. So Long's hashCode is altered to + // conform to Int's for all values in Int's range. + // + // Float is problematic because it's far too small to hold + // all the Ints, so for instance Int.MaxValue.toFloat claims + // to be == to each of the largest 64 Ints. There is no way + // to preserve equals/hashCode alignment without compromising + // the hashCode distribution, so Floats are only guaranteed + // to have the same hashCode for whole Floats in the range + // Short.MinValue to Short.MaxValue (2^16 total.) + // + // Double has its hashCode altered to match the entire Int range, + // but is not guaranteed beyond that. (But could/should it be? + // The hashCode is only 32 bits so this is a more tractable + // issue than Float's, but it might be better simply to exclude it.) + // + // Note: BigInt and BigDecimal, being arbitrary precision, could + // be made consistent with all other types for the Int range, but + // as yet have not. + // + // Note: Among primitives, Float.NaN != Float.NaN, but the boxed + // verisons are equal. This still needs reconciliation. @inline def hash(x: Any): Int = x match { case null => 0 + case x: Long => hash(x) case x: Double => hash(x) case x: Float => hash(x) - case x: java.lang.Number => hash(x) case _ => x.hashCode } @@ -266,7 +293,6 @@ object ScalaRunTime { val high = (lv >>> 32).toInt low ^ (high + lowSign) } - @inline def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x) // The remaining overloads are here for completeness, but the compiler // inlines these definitions directly so they're not generally used. diff --git a/test/files/run/hashCodeBoxesRunTime.scala b/test/files/run/hashCodeBoxesRunTime.scala deleted file mode 100644 index 081a73376e..0000000000 --- a/test/files/run/hashCodeBoxesRunTime.scala +++ /dev/null @@ -1,28 +0,0 @@ -// This only tests direct access to the methods in BoxesRunTime, -// not the whole scheme. -object Test -{ - import java.{ lang => jl } - import scala.runtime.BoxesRunTime.{ hashFromNumber, hashFromObject } - - def allSame[T](xs: List[T]) = assert(xs.distinct.size == 1, "failed: " + xs) - - def mkNumbers(x: Int): List[Number] = - List(x.toByte, x.toShort, x, x.toLong, x.toFloat, x.toDouble) - - def testLDF(x: Long) = allSame(List[Number](x, x.toDouble, x.toFloat) map hashFromNumber) - - def main(args: Array[String]): Unit = { - List(Byte.MinValue, -1, 0, 1, Byte.MaxValue) foreach { n => - val hashes = mkNumbers(n) map hashFromNumber - allSame(hashes) - if (n >= 0) { - val charCode = hashFromObject(n.toChar: Character) - assert(charCode == hashes.head) - } - } - - testLDF(Short.MaxValue.toLong) - testLDF(Short.MinValue.toLong) - } -} diff --git a/test/files/run/hashCodeScalaRunTime.scala b/test/files/run/hashCodeScalaRunTime.scala new file mode 100644 index 0000000000..e352af95f1 --- /dev/null +++ b/test/files/run/hashCodeScalaRunTime.scala @@ -0,0 +1,28 @@ +// This only tests direct access to the methods in ScalaRunTime, +// not the whole scheme. +object Test +{ + import java.{ lang => jl } + import scala.runtime.ScalaRunTime.{ hash } + + def allSame[T](xs: List[T]) = assert(xs.distinct.size == 1, "failed: " + xs) + + def mkNumbers(x: Int): List[Number] = + List(x.toByte, x.toShort, x, x.toLong, x.toFloat, x.toDouble) + + def testLDF(x: Long) = allSame(List[Number](x, x.toDouble, x.toFloat) map hash) + + def main(args: Array[String]): Unit = { + List(Byte.MinValue, -1, 0, 1, Byte.MaxValue) foreach { n => + val hashes = mkNumbers(n) map hash + allSame(hashes) + if (n >= 0) { + val charCode = hash(n.toChar: Character) + assert(charCode == hashes.head) + } + } + + testLDF(Short.MaxValue.toLong) + testLDF(Short.MinValue.toLong) + } +} diff --git a/test/files/run/hashhash.scala b/test/files/run/hashhash.scala index dc31df8cfa..f9fc067398 100644 --- a/test/files/run/hashhash.scala +++ b/test/files/run/hashhash.scala @@ -9,7 +9,15 @@ object Test { val x = (BigInt(1) << 64).toDouble val y: Any = x + val f: Float = x.toFloat + val jn: java.lang.Number = x + val jf: java.lang.Float = x.toFloat + val jd: java.lang.Double = x assert(x.## == y.##, ((x, y))) + assert(x.## == f.##, ((x, f))) + assert(x.## == jn.##, ((x, jn))) + assert(x.## == jf.##, ((x, jf))) + assert(x.## == jd.##, ((x, jd))) } } -- cgit v1.2.3