summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala5
-rw-r--r--src/library/scala/collection/Iterator.scala3
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java61
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala41
-rw-r--r--test/files/run/hashCodeScalaRunTime.scala (renamed from test/files/run/hashCodeBoxesRunTime.scala)10
-rw-r--r--test/files/run/hashhash.scala13
-rw-r--r--test/files/run/t1247.check1
-rw-r--r--test/files/run/t1247.scala11
-rw-r--r--test/files/run/t4190.check3
-rw-r--r--test/files/run/t4190.scala6
-rw-r--r--test/files/run/t5328.check3
-rw-r--r--test/files/run/t5328.scala5
13 files changed, 96 insertions, 76 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index ef98935f9c..7f220992a3 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -473,7 +473,15 @@ abstract class UnCurry extends InfoTransform
arg.pos.source.path + ":" + arg.pos.line, fun.fullName,
if (fun.isPrivate) "private" else "")
)
- newFunction0(arg)
+
+ arg match {
+ // don't add a thunk for by-name argument if argument already is an application of
+ // a Function0. We can then remove the application and use the existing Function0.
+ case Apply(Select(recv, nme.apply), Nil) if recv.tpe.typeSymbol isSubClass FunctionClass(0) =>
+ recv
+ case _ =>
+ newFunction0(arg)
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index e60cda6af7..6bed0b1228 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -386,8 +386,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("cannot be used here - classes can only override abstract types");
} else if (other.isEffectivelyFinal) { // (1.2)
overrideError("cannot override final member");
- // synthetic exclusion needed for (at least) default getters.
- } else if (!other.isDeferred && !member.isAnyOverride && !member.isSynthetic) {
+ } else if (!other.isDeferred && !member.isAnyOverride && !member.isSynthetic) { // (*)
+ // (*) Synthetic exclusion for (at least) default getters, fixes SI-5178. We cannot assign the OVERRIDE flag to
+ // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket.
if (isNeitherInClass && !(other.owner isSubClass member.owner))
emitOverrideError(
clazz + " inherits conflicting members:\n "
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/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 4c5e0e408b..6bf25b8464 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -233,11 +233,41 @@ 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
+ //
+ // 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
+ // versions 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.hashCode
+ }
@inline def hash(dv: Double): Int = {
val iv = dv.toInt
@@ -263,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/hashCodeScalaRunTime.scala
index 081a73376e..e352af95f1 100644
--- a/test/files/run/hashCodeBoxesRunTime.scala
+++ b/test/files/run/hashCodeScalaRunTime.scala
@@ -1,23 +1,23 @@
-// This only tests direct access to the methods in BoxesRunTime,
+// This only tests direct access to the methods in ScalaRunTime,
// not the whole scheme.
object Test
{
import java.{ lang => jl }
- import scala.runtime.BoxesRunTime.{ hashFromNumber, hashFromObject }
+ 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 hashFromNumber)
+ 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 hashFromNumber
+ val hashes = mkNumbers(n) map hash
allSame(hashes)
if (n >= 0) {
- val charCode = hashFromObject(n.toChar: Character)
+ val charCode = hash(n.toChar: Character)
assert(charCode == hashes.head)
}
}
diff --git a/test/files/run/hashhash.scala b/test/files/run/hashhash.scala
index b9cec99a12..f9fc067398 100644
--- a/test/files/run/hashhash.scala
+++ b/test/files/run/hashhash.scala
@@ -6,5 +6,18 @@ 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
+ 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)))
}
}
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())
+}
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
+}
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 ",")
+}