summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala44
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala6
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java311
-rw-r--r--src/library/scala/runtime/Equality.java58
5 files changed, 140 insertions, 291 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index e1429b1644..eb6017815a 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -825,8 +825,6 @@ trait ScalacSettings {
withHelpSyntax("-Ysqueeze:<enabled>")
val Ystatistics = BooleanSetting ("-Ystatistics", "Print compiler statistics")
val stop = PhasesSetting ("-Ystop", "Stop after phase")
- val logEquality = BooleanSetting ("-Ylog-equality", "Log all noteworthy equality tests (hardcoded to /tmp/scala-equality-log.txt)") .
- withPostSetHook(() => scala.runtime.Equality.logEverything = true)
val refinementMethodDispatch =
ChoiceSetting ("-Ystruct-dispatch", "Selects dispatch method for structural refinement method calls",
List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") .
@@ -838,6 +836,16 @@ trait ScalacSettings {
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
val Ytailrec = BooleanSetting ("-Ytailrecommend", "Alert methods which would be tail-recursive if private or final.")
+ // Equality specific
+ val logEqEq = BooleanSetting ("-Ylog-eqeq", "Log all noteworthy equality tests") .
+ withPostSetHook(() => scala.runtime.Equality.logEverything = true)
+ val YfutureEqEq = BooleanSetting ("-Yfuture-eqeq", "Use proposed overloading-based numeric equality semantics.") .
+ withPostSetHook(() => scala.runtime.Equality.use28Semantics = true)
+ val YwarnEqEq = BooleanSetting ("-Ywarn-eqeq", "Warn when boxed primitives of different types are compared.") .
+ withPostSetHook(() => scala.runtime.Equality.warnOnBoxedCompare = true)
+ val YdieEqEq = BooleanSetting ("-Ydie-changed-eqeq", "Throw an exception if a comparison would have come back differently in scala 2.7.") .
+ withPostSetHook(() => scala.runtime.Equality.dieOnBoxedCompareIfValuesAreEqual = true)
+
// Warnings
val Xwarninit = BooleanSetting ("-Xwarninit", "Warn about possible changes in initialization semantics")
val Xchecknull = BooleanSetting ("-Xcheck-null", "Emit warning on selection of nullable reference")
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b3d7da8f06..99f0d4cf3c 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1291,7 +1291,7 @@ abstract class GenICode extends SubComponent {
elseCtx: Context): Unit =
{
def genComparisonOp(l: Tree, r: Tree, code: Int) {
- if (settings.logEquality.value && isUniversalEqualityOp(code))
+ if (settings.logEqEq.value && isUniversalEqualityOp(code))
logEqEq(tree, l, r, code)
val op: TestOp = code match {
@@ -1422,9 +1422,13 @@ abstract class GenICode extends SubComponent {
(rsym == ObjectClass) ||
(lsym != rsym) && (isBoxed(lsym) || isBoxed(rsym))
}
+ def cannotAvoidBoxesRuntime =
+ settings.logEqEq.value || settings.YwarnEqEq.value || settings.YdieEqEq.value
- if (mustUseAnyComparator) {
-
+ /** We can avoid generating calls to BoxesRuntime only if -Yfuture-eqeq
+ * is enabled AND none of the eqeq logging options are enabled.
+ */
+ if (mustUseAnyComparator && (!settings.YfutureEqEq.value || cannotAvoidBoxesRuntime)) {
val ctx1 = genLoad(l, ctx, ANY_REF_CLASS)
val ctx2 = genLoad(r, ctx1, ANY_REF_CLASS)
ctx2.bb.emitOnly(
@@ -1433,7 +1437,6 @@ abstract class GenICode extends SubComponent {
)
}
else {
-
if (isNull(l))
// null == expr -> expr eq null
genLoad(r, ctx, ANY_REF_CLASS).bb emitOnly CZJUMP(thenCtx.bb, elseCtx.bb, EQ, ANY_REF_CLASS)
@@ -2153,39 +2156,18 @@ abstract class GenICode extends SubComponent {
override def varsInScope: Buffer[Local] = new ListBuffer
}
- /** Log equality tests to file if they are playing with typefire */
+ /** Log equality tests between different primitives. */
def logEqEq(tree: Tree, l: Tree, r: Tree, code: Int) {
import definitions._
val op = if (code == scalaPrimitives.EQ) "==" else if (code == scalaPrimitives.NE) "!=" else "??"
-
- def mayBeNumericComparison: Boolean = {
- def isPossiblyBoxed(sym: Symbol): Boolean = {
- import definitions._
- // classes as which a boxed primitive may statically appear
- val possibleBoxes = List(BoxedNumberClass, BoxedCharacterClass, SerializableClass, ComparableClass)
-
- (sym == ObjectClass) || (possibleBoxes exists (sym isNonBottomSubClass _))
- }
-
- val lsym = l.tpe.typeSymbol
- val rsym = r.tpe.typeSymbol
-
- def isSameBox = {
- def isFinalBox(s: Symbol) = (s isNonBottomSubClass BoxedNumberClass) && s.isFinal
- isFinalBox(lsym) && isFinalBox(rsym) && lsym == rsym
- }
- isPossiblyBoxed(lsym) && isPossiblyBoxed(rsym) && !isSameBox
- }
-
val tkl = toTypeKind(l.tpe)
val tkr = toTypeKind(r.tpe)
- lazy val whereAreWe = tree.pos.source + ":" + tree.pos.line
- def logit(preface: String) =
- runtime.Equality.log("[%s] %s %s %s (%s)".format(preface, l.tpe, op, r.tpe, whereAreWe))
if (tkl.isNumericType && tkr.isNumericType && tkl != tkr)
- logit(" KNOWN ")
- else if (mayBeNumericComparison)
- logit("UNKNOWN")
+ runtime.Equality.logComparison(
+ "Comparing actual primitives",
+ "%s %s %s".format(l.tpe, op, r.tpe),
+ tree.pos.source + ":" + tree.pos.line
+ )
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
index a46a987bb8..12f6f4021b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
@@ -70,6 +70,12 @@ abstract class ConstantFolder {
}
private def foldBinop(op: Name, x: Constant, y: Constant): Constant = try {
+ // temporarily logging folded ==/!= so the log doesn't have unexplained absences
+ if ((op == nme.EQ || op == nme.NE) && x.tag != y.tag && settings.logEqEq.value) {
+ val opstr = if (op == nme.EQ) "==" else "!="
+ scala.runtime.Equality.log("Folding constant expression (%s %s %s)".format(x.value, opstr, y.value))
+ }
+
val optag = if (x.tag == y.tag) x.tag
else if (isNumeric(x.tag) && isNumeric(y.tag))
if (x.tag > y.tag) x.tag else y.tag
diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java
index 010e2738c9..3e75cb213e 100644
--- a/src/library/scala/runtime/BoxesRunTime.java
+++ b/src/library/scala/runtime/BoxesRunTime.java
@@ -33,15 +33,19 @@ public class BoxesRunTime
private static int typeCode(Object a) {
if (a instanceof Integer) return INT;
+ if (a instanceof Byte) return BYTE;
if (a instanceof Character) return CHAR;
if (a instanceof Long) return LONG;
if (a instanceof Double) return DOUBLE;
- if (a instanceof Float) return FLOAT;
- if (a instanceof Byte) return BYTE;
if (a instanceof Short) return SHORT;
+ if (a instanceof Float) return FLOAT;
return OTHER;
}
+ private static String boxDescription(Object a) {
+ return "" + a.getClass().getSimpleName() + "(" + a + ")";
+ }
+
/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */
public static Boolean boxToBoolean(boolean b) {
@@ -135,221 +139,7 @@ public class BoxesRunTime
/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
- /** These methods manually implement "overloading" among boxed primitives.
- * The compiler is capable of inserting (but does not presently) the specific
- * equals method based on the statically known types of the boxes.
- */
-
- public static boolean equalsCharacterCharacter(Character a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.charValue();
- }
- public static boolean equalsCharacterByte(Character a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.byteValue();
- }
- public static boolean equalsCharacterShort(Character a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.shortValue();
- }
- public static boolean equalsCharacterInteger(Character a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.intValue();
- }
- public static boolean equalsCharacterLong(Character a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.longValue();
- }
- public static boolean equalsCharacterFloat(Character a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.floatValue();
- }
- public static boolean equalsCharacterDouble(Character a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.doubleValue();
- }
- public static boolean equalsByteCharacter(Byte a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.charValue();
- }
- public static boolean equalsByteByte(Byte a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.byteValue();
- }
- public static boolean equalsByteShort(Byte a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.shortValue();
- }
- public static boolean equalsByteInteger(Byte a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.intValue();
- }
- public static boolean equalsByteLong(Byte a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.longValue();
- }
- public static boolean equalsByteFloat(Byte a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.floatValue();
- }
- public static boolean equalsByteDouble(Byte a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.doubleValue();
- }
- public static boolean equalsShortCharacter(Short a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.charValue();
- }
- public static boolean equalsShortByte(Short a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.byteValue();
- }
- public static boolean equalsShortShort(Short a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.shortValue();
- }
- public static boolean equalsShortInteger(Short a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.intValue();
- }
- public static boolean equalsShortLong(Short a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.longValue();
- }
- public static boolean equalsShortFloat(Short a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.floatValue();
- }
- public static boolean equalsShortDouble(Short a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.doubleValue();
- }
- public static boolean equalsIntegerCharacter(Integer a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.charValue();
- }
- public static boolean equalsIntegerByte(Integer a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.byteValue();
- }
- public static boolean equalsIntegerShort(Integer a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.shortValue();
- }
- public static boolean equalsIntegerInteger(Integer a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.intValue();
- }
- public static boolean equalsIntegerLong(Integer a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.longValue();
- }
- public static boolean equalsIntegerFloat(Integer a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.floatValue();
- }
- public static boolean equalsIntegerDouble(Integer a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.doubleValue();
- }
- public static boolean equalsLongCharacter(Long a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.charValue();
- }
- public static boolean equalsLongByte(Long a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.byteValue();
- }
- public static boolean equalsLongShort(Long a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.shortValue();
- }
- public static boolean equalsLongInteger(Long a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.intValue();
- }
- public static boolean equalsLongLong(Long a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.longValue();
- }
- public static boolean equalsLongFloat(Long a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.floatValue();
- }
- public static boolean equalsLongDouble(Long a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.doubleValue();
- }
- public static boolean equalsFloatCharacter(Float a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.charValue();
- }
- public static boolean equalsFloatByte(Float a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.byteValue();
- }
- public static boolean equalsFloatShort(Float a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.shortValue();
- }
- public static boolean equalsFloatInteger(Float a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.intValue();
- }
- public static boolean equalsFloatLong(Float a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.longValue();
- }
- public static boolean equalsFloatFloat(Float a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.floatValue();
- }
- public static boolean equalsFloatDouble(Float a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.doubleValue();
- }
- public static boolean equalsDoubleCharacter(Double a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.charValue();
- }
- public static boolean equalsDoubleByte(Double a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.byteValue();
- }
- public static boolean equalsDoubleShort(Double a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.shortValue();
- }
- public static boolean equalsDoubleInteger(Double a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.intValue();
- }
- public static boolean equalsDoubleLong(Double a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.longValue();
- }
- public static boolean equalsDoubleFloat(Double a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.floatValue();
- }
- public static boolean equalsDoubleDouble(Double a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.doubleValue();
- }
-
- /** The current equals method, whose logic is under review. **/
-
- public static boolean equals(Object a, Object b) {
- if ((a instanceof Number || a instanceof Character) && (b instanceof Number || b instanceof Character)) {
- if (a.getClass() != b.getClass()) {
- Equality.logInternal("[ BOXED ] Comparing: ", a, b, Equality.whereAreWe());
- }
- }
-
- if (a == null || b == null)
- return a == b;
- if (a.equals(b))
- return true;
+ private static boolean equalsBonusLogicFromScala27(Object a, Object b) {
if (a instanceof Number || a instanceof Character || b instanceof Number || b instanceof Character) {
int acode = typeCode(a);
int bcode = typeCode(b);
@@ -376,18 +166,45 @@ public class BoxesRunTime
res = (aa == bb);
}
- if (res || b.equals(a)) {
- String msg;
- if (res) msg = "[ BOXED ] Overriding equals between different types: ";
- else msg = "[ BOXED ] Overriding equals because b.equals(a): ";
- Equality.logInternal(msg, a, b, Equality.whereAreWe());
- return true;
- }
- return false;
+ if (res || b.equals(a)) return true;
+ else return false;
}
return false;
}
+ private static String logMessage(Object a, Object b, String where) {
+ return "Compared boxed primitives (" + boxDescription(a) + " == " + boxDescription(b) + ") @ " + where;
+ }
+
+ private static void verifyEqEq(Object a, Object b, boolean isFatal, boolean onlyIfActuallyEqual) {
+ int code1 = typeCode(a);
+ int code2 = typeCode(b);
+
+ if (code1 < OTHER && code2 < OTHER && code1 != code2) {
+ if (!onlyIfActuallyEqual || equalsBonusLogicFromScala27(a, b)) {
+ String msg = logMessage(a, b, Equality.whereAreWe(5));
+ Equality.warnOrDie(msg, isFatal);
+ }
+ }
+ }
+
+ /** The current equals method. **/
+ public static boolean equals(Object a, Object b) {
+ if (a == null || b == null)
+ return a == b;
+
+ verifyEqEq(a, b,
+ (Equality.dieOnBoxedCompare || Equality.dieOnBoxedCompareIfValuesAreEqual),
+ (Equality.warnOnBoxedCompareIfValuesAreEqual || Equality.dieOnBoxedCompareIfValuesAreEqual)
+ );
+
+ if (a.equals(b))
+ return true;
+
+ if (Equality.use28Semantics) return false;
+ else return equalsBonusLogicFromScala27(a, b);
+ }
+
/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */
/** arg1 + arg2 */
@@ -889,11 +706,11 @@ public class BoxesRunTime
/** arg.toChar */
public static Character toCharacter(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return (Character)arg;
- if (arg instanceof Byte) return boxToCharacter((char)unboxToByte(arg));
- if (arg instanceof Short) return boxToCharacter((char)unboxToShort(arg));
if (arg instanceof Integer) return boxToCharacter((char)unboxToInt(arg));
+ if (arg instanceof Short) return boxToCharacter((char)unboxToShort(arg));
+ if (arg instanceof Character) return (Character)arg;
if (arg instanceof Long) return boxToCharacter((char)unboxToLong(arg));
+ if (arg instanceof Byte) return boxToCharacter((char)unboxToByte(arg));
if (arg instanceof Float) return boxToCharacter((char)unboxToFloat(arg));
if (arg instanceof Double) return boxToCharacter((char)unboxToDouble(arg));
throw new NoSuchMethodException();
@@ -901,11 +718,11 @@ public class BoxesRunTime
/** arg.toByte */
public static Byte toByte(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Integer) return boxToByte((byte)unboxToInt(arg));
if (arg instanceof Character) return boxToByte((byte)unboxToChar(arg));
if (arg instanceof Byte) return (Byte)arg;
- if (arg instanceof Short) return boxToByte((byte)unboxToShort(arg));
- if (arg instanceof Integer) return boxToByte((byte)unboxToInt(arg));
if (arg instanceof Long) return boxToByte((byte)unboxToLong(arg));
+ if (arg instanceof Short) return boxToByte((byte)unboxToShort(arg));
if (arg instanceof Float) return boxToByte((byte)unboxToFloat(arg));
if (arg instanceof Double) return boxToByte((byte)unboxToDouble(arg));
throw new NoSuchMethodException();
@@ -913,11 +730,11 @@ public class BoxesRunTime
/** arg.toShort */
public static Short toShort(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Integer) return boxToShort((short)unboxToInt(arg));
+ if (arg instanceof Long) return boxToShort((short)unboxToLong(arg));
if (arg instanceof Character) return boxToShort((short)unboxToChar(arg));
if (arg instanceof Byte) return boxToShort((short)unboxToByte(arg));
if (arg instanceof Short) return (Short)arg;
- if (arg instanceof Integer) return boxToShort((short)unboxToInt(arg));
- if (arg instanceof Long) return boxToShort((short)unboxToLong(arg));
if (arg instanceof Float) return boxToShort((short)unboxToFloat(arg));
if (arg instanceof Double) return boxToShort((short)unboxToDouble(arg));
throw new NoSuchMethodException();
@@ -925,49 +742,49 @@ public class BoxesRunTime
/** arg.toInt */
public static Integer toInteger(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return boxToInteger((int)unboxToChar(arg));
- if (arg instanceof Byte) return boxToInteger((int)unboxToByte(arg));
- if (arg instanceof Short) return boxToInteger((int)unboxToShort(arg));
if (arg instanceof Integer) return (Integer)arg;
if (arg instanceof Long) return boxToInteger((int)unboxToLong(arg));
- if (arg instanceof Float) return boxToInteger((int)unboxToFloat(arg));
if (arg instanceof Double) return boxToInteger((int)unboxToDouble(arg));
+ if (arg instanceof Float) return boxToInteger((int)unboxToFloat(arg));
+ if (arg instanceof Character) return boxToInteger((int)unboxToChar(arg));
+ if (arg instanceof Byte) return boxToInteger((int)unboxToByte(arg));
+ if (arg instanceof Short) return boxToInteger((int)unboxToShort(arg));
throw new NoSuchMethodException();
}
/** arg.toLong */
public static Long toLong(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Integer) return boxToLong((long)unboxToInt(arg));
+ if (arg instanceof Double) return boxToLong((long)unboxToDouble(arg));
+ if (arg instanceof Float) return boxToLong((long)unboxToFloat(arg));
+ if (arg instanceof Long) return (Long)arg;
if (arg instanceof Character) return boxToLong((long)unboxToChar(arg));
if (arg instanceof Byte) return boxToLong((long)unboxToByte(arg));
if (arg instanceof Short) return boxToLong((long)unboxToShort(arg));
- if (arg instanceof Integer) return boxToLong((long)unboxToInt(arg));
- if (arg instanceof Long) return (Long)arg;
- if (arg instanceof Float) return boxToLong((long)unboxToFloat(arg));
- if (arg instanceof Double) return boxToLong((long)unboxToDouble(arg));
throw new NoSuchMethodException();
}
/** arg.toFloat */
public static Float toFloat(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return boxToFloat((float)unboxToChar(arg));
- if (arg instanceof Byte) return boxToFloat((float)unboxToByte(arg));
- if (arg instanceof Short) return boxToFloat((float)unboxToShort(arg));
if (arg instanceof Integer) return boxToFloat((float)unboxToInt(arg));
if (arg instanceof Long) return boxToFloat((float)unboxToLong(arg));
if (arg instanceof Float) return (Float)arg;
if (arg instanceof Double) return boxToFloat((float)unboxToDouble(arg));
+ if (arg instanceof Character) return boxToFloat((float)unboxToChar(arg));
+ if (arg instanceof Byte) return boxToFloat((float)unboxToByte(arg));
+ if (arg instanceof Short) return boxToFloat((float)unboxToShort(arg));
throw new NoSuchMethodException();
}
/** arg.toDouble */
public static Double toDouble(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return boxToDouble((double)unboxToChar(arg));
- if (arg instanceof Byte) return boxToDouble((double)unboxToByte(arg));
- if (arg instanceof Short) return boxToDouble((double)unboxToShort(arg));
if (arg instanceof Integer) return boxToDouble((double)unboxToInt(arg));
- if (arg instanceof Long) return boxToDouble((double)unboxToLong(arg));
if (arg instanceof Float) return boxToDouble((double)unboxToFloat(arg));
if (arg instanceof Double) return (Double)arg;
+ if (arg instanceof Long) return boxToDouble((double)unboxToLong(arg));
+ if (arg instanceof Character) return boxToDouble((double)unboxToChar(arg));
+ if (arg instanceof Byte) return boxToDouble((double)unboxToByte(arg));
+ if (arg instanceof Short) return boxToDouble((double)unboxToShort(arg));
throw new NoSuchMethodException();
}
diff --git a/src/library/scala/runtime/Equality.java b/src/library/scala/runtime/Equality.java
index 3ec89360b8..018b3b4c07 100644
--- a/src/library/scala/runtime/Equality.java
+++ b/src/library/scala/runtime/Equality.java
@@ -12,6 +12,11 @@
package scala.runtime;
import java.io.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.Handler;
+import java.util.logging.StreamHandler;
+import java.util.logging.SimpleFormatter;
/** An object (static class) encapsulating the variations on equality
* presently under consideration. It's written in java so it can easily
@@ -19,33 +24,64 @@ import java.io.*;
*/
public class Equality
{
- public static boolean disallowNullEquals = true;
- public static boolean disallowPrimitiveEquals = true;
- public static boolean warnOnEqualsAny = true;
- public static boolean callCanEqualIfAvailable = true;
public static boolean logEverything = false;
+ public static boolean use28Semantics = false;
+
+ public static boolean warnOnBoxedCompare = false;
+ public static boolean warnOnBoxedCompareIfValuesAreEqual = false;
+ public static boolean dieOnBoxedCompare = false;
+ public static boolean dieOnBoxedCompareIfValuesAreEqual = false;
+
+ private static Handler handler;
+ public static Logger logger;
+ public static final Logger defaultLogger;
+
+ static {
+ class EqualityLogger extends Logger {
+ EqualityLogger() {
+ super("EqualityLogger", null);
+ }
+ }
+ defaultLogger = new EqualityLogger();
+
+ handler = new StreamHandler(System.out, new SimpleFormatter());
+ handler.setLevel(Level.INFO);
+ defaultLogger.addHandler(handler);
+
+ logger = defaultLogger;
+ }
+
+ public static void warnOrDie(String msg, boolean isFatal) {
+ if (isFatal) throw new RuntimeException(msg);
+ else log(msg);
+ // else System.out.println(msg);
+ }
public static String obToString(Object o) {
String s = o.toString() + " (" + o.getClass().getSimpleName() + ")";
return s.replaceAll("\\n", " ");
}
- public static void logInternal(String msg, Object a, Object b, String where) {
- log(String.format("%s %s == %s at %s", msg, obToString(a), obToString(b), where));
+ public static void logComparison(String msg, String cmp, String where) {
+ log(String.format("%s (%s) at %s", msg, cmp, where));
}
- public static String whereAreWe() {
+ public static String whereAreWe() { return whereAreWe(4); }
+ public static String whereAreWe(int depth) {
StackTraceElement[] es = Thread.currentThread().getStackTrace();
- if (es.length < 4)
+ if (es.length < depth)
return "<unknown>";
- StackTraceElement e = es[3];
+ StackTraceElement e = es[depth - 1];
String clazz = e.getClassName().replaceAll("\\$.*$", "\\$...");
return String.format("%s.%s(%s.%d)", clazz, e.getMethodName(), e.getFileName(), e.getLineNumber());
}
public static void log(String msg) {
- if (logEverything)
- System.out.println(msg);
+ if (logger != null) {
+ logger.warning(msg);
+ handler.flush();
+ }
+ else System.out.println(msg);
}
}