diff options
author | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2008-02-06 18:02:39 +0000 |
---|---|---|
committer | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2008-02-06 18:02:39 +0000 |
commit | 11d8e2c4870d13be7b4a651495aae8fb8946d60f (patch) | |
tree | 6e6f0534d1fd9edb843de85adec93425481879de | |
parent | 9b379d01bf4c1653d015d70aee8df71be8a6904e (diff) | |
download | scala-11d8e2c4870d13be7b4a651495aae8fb8946d60f.tar.gz scala-11d8e2c4870d13be7b4a651495aae8fb8946d60f.tar.bz2 scala-11d8e2c4870d13be7b4a651495aae8fb8946d60f.zip |
Partial fix to #397.
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 10 | ||||
-rw-r--r-- | src/library/scala/runtime/BoxesUtility.java | 168 | ||||
-rw-r--r-- | src/library/scala/runtime/Comparator.java | 80 | ||||
-rw-r--r-- | src/library/scala/runtime/ScalaRunTime.scala | 7 | ||||
-rw-r--r-- | test/files/run/structural.check | 2 | ||||
-rw-r--r-- | test/files/run/structural.scala | 23 |
7 files changed, 40 insertions, 251 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index f3953792f3..bb582faba1 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -260,6 +260,7 @@ trait StdNames { val booleanValue = newTermName("booleanValue") val box = newTermName("box") val boxArray = newTermName("boxArray") + val forceBoxedArray = newTermName("forceBoxedArray") val checkInitialized = newTermName("checkInitialized") val classOf = newTermName("classOf") val coerce = newTermName("coerce") diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index b1088dd599..1969880022 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -746,16 +746,20 @@ trait Typers { self: Analyzer => assert((mode & HKmode) == 0) //@M instantiate(tree, mode, pt) } else if (tree.tpe <:< pt) { - def isStructuralType(tpe: Type) = tpe match { + def isStructuralType(tpe: Type): Boolean = tpe match { case RefinedType(ps, decls) => decls.toList exists (x => x.isTerm && x.allOverriddenSymbols.isEmpty) case _ => false } if (isStructuralType(pt) && tree.tpe.typeSymbol == ArrayClass) { - println("need to insert box for "+tree) + // all Arrays used as structural refinement typed values must be boxed + // this does not solve the case where the type to be adapted to comes + // from a type variable that was bound by a strctural but is instantiated + typed(Apply(Select(gen.mkAttributedRef(ScalaRunTimeModule), nme.forceBoxedArray), List(tree))) } - tree + else + tree } else { if ((mode & PATTERNmode) != 0) { if ((tree.symbol ne null) && tree.symbol.isModule) diff --git a/src/library/scala/runtime/BoxesUtility.java b/src/library/scala/runtime/BoxesUtility.java deleted file mode 100644 index bf065e7dbe..0000000000 --- a/src/library/scala/runtime/BoxesUtility.java +++ /dev/null @@ -1,168 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - -/** - * @author Gilles Dubochet - * @version 1.0 - */ -public class BoxesUtility { - - private static int charLowBound = 0; - private static int charUpBound = 255; - private static Character[] charCache = new Character[charUpBound - charLowBound + 1]; - - private static int byteLowBound = -128; - private static int byteUpBound = 127; - private static Byte[] byteCache = new Byte[byteUpBound - byteLowBound + 1]; - - private static int shortLowBound = -128; - private static int shortUpBound = 127; - private static Short[] shortCache = new Short[shortUpBound - shortLowBound + 1]; - - private static int intLowBound = -128; - private static int intUpBound = 1024; - private static Integer[] intCache = new Integer[intUpBound - intLowBound + 1]; - - private static int longLowBound = -128; - private static int longUpBound = 1024; - private static Long[] longCache = new Long[longUpBound - longLowBound + 1]; - - static { - int idx = 0; - while (idx <= charUpBound - charLowBound) { - charCache[idx] = new Character((char)(idx + charLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= byteUpBound - byteLowBound) { - byteCache[idx] = new Byte((byte)(idx + byteLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= shortUpBound - shortLowBound) { - shortCache[idx] = new Short((short)(idx + shortLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= intUpBound - intLowBound) { - intCache[idx] = new Integer((int)(idx + intLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= longUpBound - longLowBound) { - longCache[idx] = new Long((long)(idx + longLowBound)); - idx = idx + 1; - } - } - - public static Boolean boxToBoolean(boolean b) { - return b ? Boolean.TRUE : Boolean.FALSE; - } - - public static Character boxToCharacter(char c) { - if (c >= charLowBound && c <= charUpBound) - return charCache[(int)c - charLowBound]; - else - return new Character(c); - } - - public static Byte boxToByte(byte b) { - if (b >= byteLowBound && b <= byteUpBound) - return byteCache[(int)b - byteLowBound]; - else - return new Byte(b); - } - - public static Short boxToShort(short s) { - if (s >= shortLowBound && s <= shortUpBound) - return shortCache[(int)s - shortLowBound]; - else - return new Short(s); - } - - public static Integer boxToInteger(int i) { - if (i >= intLowBound && i <= intUpBound) - return intCache[(int)i - intLowBound]; - else - return new Integer(i); - } - - public static Long boxToLong(long l) { - if (l >= longLowBound && l <= longUpBound) - return longCache[(int)l - longLowBound]; - else - return new Long(l); - } - - public static Float boxToFloat(float f) { - return new Float(f); - } - - public static Double boxToDouble(double d) { - return new Double(d); - } - - public static boolean unboxToBoolean(Object b) { - return b == null ? false : ((Boolean)b).booleanValue(); - } - - public static char unboxToChar(Object c) { - if (c == null) - return 0; - else - return ((Character)c).charValue(); - } - - public static byte unboxToByte(Object b) { - if (b == null) - return 0; - else - return ((Byte)b).byteValue(); - } - - public static short unboxToShort(Object s) { - if (s == null) - return 0; - else - return ((Short)s).shortValue(); - } - - public static int unboxToInt(Object i) { - if (i == null) - return 0; - else - return ((Integer)i).intValue(); - } - - public static long unboxToLong(Object l) { - if (l == null) - return 0; - else - return ((Long)l).longValue(); - } - - public static float unboxToFloat(Object f) { - if (f == null) - return 0.0f; - else - return ((Float)f).floatValue(); - } - - public static double unboxToDouble(Object d) { - if (d == null) - return 0.0; - else - return ((Double)d).doubleValue(); - } - -} diff --git a/src/library/scala/runtime/Comparator.java b/src/library/scala/runtime/Comparator.java deleted file mode 100644 index cd4303c79f..0000000000 --- a/src/library/scala/runtime/Comparator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - -/** An object (static class) providing a correct notion of equality in - * the general case, in particular with boxed values. - * - * @author Gilles Dubochet - * @author Martin Odersky - * @contributor Stepan Koltsov - * @version 1.2 - */ -public class Comparator { - - private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7; - - private static int typeCode(Object a) { - if (a instanceof Integer) return INT; - 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; - return OTHER; - } - - /** A rich implementation of the <code>equals</code> method that overrides the - * default equals because Java's boxed primitives are utterly broken. This equals - * is inserted instead of a normal equals by the Scala compiler (in the - * ICode phase, method <code>genEqEqPrimitive</code>) only when either - * side of the comparison is a subclass of <code>AnyVal</code>, of - * <code>java.lang.Number</code>, of <code>java.lang.Character</code> or - * is exactly <code>Any</code> or <code>AnyRef</code>. - */ - public static boolean equals(Object a, Object b) { - if (a == null || b == null) - return a == b; - else if (a.equals(b)) - return true; - else if (a instanceof Number || a instanceof Character || b instanceof Number || b instanceof Character) { - int acode = typeCode(a); - int bcode = typeCode(b); - int maxcode = (acode < bcode) ? bcode : acode; - if (maxcode <= INT) { - int aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).intValue(); - int bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).intValue(); - return aa == bb; - } - else if (maxcode <= LONG) { - long aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).longValue(); - long bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).longValue(); - return aa == bb; - } - else if (maxcode <= FLOAT) { - float aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).floatValue(); - float bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).floatValue(); - return aa == bb; - } - else if (maxcode <= DOUBLE) { - double aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).doubleValue(); - double bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).doubleValue(); - return aa == bb; - } - else - return b.equals(a); - } - else - return false; - } -} diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index d7a0776f36..a44046985d 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -32,6 +32,13 @@ object ScalaRunTime { def isValueTag(tag: String) = tag.charAt(0) == '.' def isValueClass(clazz: Class[_]) = clazz.isPrimitive() + def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = { + val array = new Array[A](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + def checkInitialized[T <: AnyRef](x: T): T = if (x == null) throw new UninitializedError else x diff --git a/test/files/run/structural.check b/test/files/run/structural.check index 52292fcb36..be65e6a732 100644 --- a/test/files/run/structural.check +++ b/test/files/run/structural.check @@ -33,3 +33,5 @@ 4 5 caught +3 +2 diff --git a/test/files/run/structural.scala b/test/files/run/structural.scala index d6b2b3d09f..5fc2292b42 100644 --- a/test/files/run/structural.scala +++ b/test/files/run/structural.scala @@ -171,8 +171,31 @@ object test3 { } +object test4 { + + class A + + val aar = Array(new A, new A, new A) + val nar = Array(1, 2) + + def f(p: {def size: Int}) = println(p.size) + //def g[T <: {def size: Int}](p: T) = println(p.size) // open issue + //def h[T <% {def size: Int}](p: T) = println(p.size) // open issue + + f(aar) + f(nar) + + //g(aar) + //g(nar) + + //h(aar) + //h(nar) + +} + object Test extends Application { test1 test2 test3 + test4 } |