summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschinz <schinz@epfl.ch>2005-04-07 19:46:41 +0000
committerschinz <schinz@epfl.ch>2005-04-07 19:46:41 +0000
commit36d0dca50b187ded0a9c12e8ddd7d9332882f44f (patch)
tree201e072620dcd8b8e962d68d99e3d8e65d899929
parent87ea8ccb1a5490efb2a7f940e4402e19a9768d15 (diff)
downloadscala-36d0dca50b187ded0a9c12e8ddd7d9332882f44f.tar.gz
scala-36d0dca50b187ded0a9c12e8ddd7d9332882f44f.tar.bz2
scala-36d0dca50b187ded0a9c12e8ddd7d9332882f44f.zip
- fixed asInstanceOf when applied to null, so t...
- fixed asInstanceOf when applied to null, so that it works according to the spec, - use a local variable in the "two steps" translation of isInstanceOf, to avoid duplicated evaluation
-rw-r--r--sources/scala/Type.java28
-rw-r--r--sources/scala/runtime/types/JavaClassType.java2
-rw-r--r--sources/scalac/transformer/TypesAsValuesPhase.java50
3 files changed, 57 insertions, 23 deletions
diff --git a/sources/scala/Type.java b/sources/scala/Type.java
index 86702be8f2..cc9a2b524e 100644
--- a/sources/scala/Type.java
+++ b/sources/scala/Type.java
@@ -12,6 +12,7 @@ package scala;
import scala.runtime.RunTime;
import scala.runtime.types.ScalaClassType;
+import scala.runtime.types.JavaClassType;
import scala.runtime.types.TypeBoolean;
import scala.runtime.types.TypeByte;
import scala.runtime.types.TypeChar;
@@ -73,10 +74,19 @@ abstract public class Type implements java.io.Serializable {
*/
public Object cast(Object o) {
assert Statistics.incTypeCast();
- assert (o == null) || Statistics.decInstanceOf();
- if (! (o == null || isInstance(o)))
- throw new ClassCastException("\n" + ((ScalaObject)o).getType() + "\n" + this.toString());
- return o;
+ if (o == null) {
+ if (this.isSubType(JavaLangObject))
+ return null;
+ else
+ throw new ClassCastException();
+ } else {
+ assert Statistics.decInstanceOf();
+ if (isInstance(o))
+ return o;
+ else
+ throw new ClassCastException("\n" + ((ScalaObject)o).getType()
+ + "\n" + this.toString());
+ }
}
// Value types
@@ -96,6 +106,16 @@ abstract public class Type implements java.io.Serializable {
public static final TypeAllRef AllRef = new TypeAllRef();
public static final TypeAll All = new TypeAll();
+ private static JavaClassType JavaLangObject;
+
+ static {
+ try {
+ JavaLangObject = new JavaClassType("java.lang.Object");
+ } catch (ClassNotFoundException e) {
+ throw new Error(e);
+ }
+ }
+
public static boolean isSameType(Type[] these, Type[] those) {
if (these.length != those.length)
return false;
diff --git a/sources/scala/runtime/types/JavaClassType.java b/sources/scala/runtime/types/JavaClassType.java
index 7779162cb9..96aed1a7e2 100644
--- a/sources/scala/runtime/types/JavaClassType.java
+++ b/sources/scala/runtime/types/JavaClassType.java
@@ -36,7 +36,7 @@ public class JavaClassType extends ClassType {
return jct;
}
- private JavaClassType(String fullName) throws ClassNotFoundException {
+ public JavaClassType(String fullName) throws ClassNotFoundException {
super(Class.forName(fullName, false, loader), true);
}
}
diff --git a/sources/scalac/transformer/TypesAsValuesPhase.java b/sources/scalac/transformer/TypesAsValuesPhase.java
index 71be22e44b..3ac714b103 100644
--- a/sources/scalac/transformer/TypesAsValuesPhase.java
+++ b/sources/scalac/transformer/TypesAsValuesPhase.java
@@ -426,7 +426,7 @@ public class TypesAsValuesPhase extends Phase {
assert targs.length == 1 && vargs.length == 0;
Type type = targs[0].type;
Tree expr = transform(qualifierOf(fun));
- return isTrivial(type)
+ return (isTrivial(type) && !isSpecial(type))
? super.transform(tree)
: genInstanceTest(tree.pos, expr, type);
} else if (funSym == defs.ANY_AS) {
@@ -436,11 +436,11 @@ public class TypesAsValuesPhase extends Phase {
// asValue(T).cast(e).asInstanceOf[T]
// unless T is a trivial type for which a Java
// instance test is sufficient, in which case the
- // expression is left as is.
+ // erased version of asInstanceOf is used.
assert targs.length == 1 && vargs.length == 0;
Type type = targs[0].type;
Tree expr = transform(qualifierOf(fun));
- return isTrivial(type)
+ return (isTrivial(type) && !isSpecial(type))
? super.transform(tree)
: genTypeCast(tree.pos, expr, type);
} else if (!monoPrimitive(funSym)) {
@@ -739,10 +739,17 @@ public class TypesAsValuesPhase extends Phase {
private Tree genInstanceTest(int pos, Tree expr, Type tp) {
Tree tpVal = typeAsValue(pos, tp, currentOwner, EENV);
- if (isKnowClassType(tp) && isLocalIdent(expr)) {
- Symbol sym = expr.symbol();
+ if (isKnowClassType(tp)) {
+ Symbol val =
+ currentOwner.newVariable(pos,
+ Modifiers.SYNTHETIC,
+ Names.LOCAL(currentOwner));
+ val.setType(expr.type);
+
+ Tree valDef = gen.ValDef(val, expr);
+
Tree cheapTest =
- gen.mkIsInstanceOf(pos, gen.mkLocalRef(pos, sym), tp, true);
+ gen.mkIsInstanceOf(pos, gen.mkLocalRef(pos, val), tp, true);
Symbol weakIsInst = defs.SCALACLASSTYPE_WEAKISINSTANCE();
Tree scalaTpVal = gen.mkAsInstanceOf(pos,
tpVal,
@@ -751,12 +758,16 @@ public class TypesAsValuesPhase extends Phase {
Tree expensiveTest =
gen.mkApply_V(pos,
gen.Select(pos, scalaTpVal, weakIsInst),
- new Tree[] { expr });
- return gen.mkApply_V(pos,
- gen.Select(pos,
- cheapTest,
- defs.BOOLEAN_AND()),
- new Tree[] { expensiveTest });
+ new Tree[] { gen.mkLocalRef(pos, val) });
+
+ Tree bothTests =
+ gen.mkApply_V(pos,
+ gen.Select(pos,
+ cheapTest,
+ defs.BOOLEAN_AND()),
+ new Tree[] { expensiveTest });
+
+ return gen.mkBlock(pos, valDef, bothTests);
} else {
Tree fun = gen.Select(pos, tpVal, defs.TYPE_ISINSTANCE());
return gen.mkApply_V(pos, fun, new Tree[] { expr });
@@ -809,19 +820,22 @@ public class TypesAsValuesPhase extends Phase {
return false;
}
- private boolean isKnowClassType(Type tp) {
+ private boolean isSpecial(Type tp) {
switch (tp) {
case TypeRef(_, Symbol sym, _):
- return (sym != defs.ARRAY_CLASS) && !sym.isParameter();
+ return (sym == defs.ANY_CLASS)
+ || (sym == defs.ANYVAL_CLASS)
+ || (sym == defs.ALLREF_CLASS)
+ || (sym == defs.ALL_CLASS);
default:
return false;
}
}
- private boolean isLocalIdent(Tree tree) {
- switch (tree) {
- case Ident(_):
- return tree.symbol().isLocal();
+ private boolean isKnowClassType(Type tp) {
+ switch (tp) {
+ case TypeRef(_, Symbol sym, _):
+ return (sym != defs.ARRAY_CLASS) && !sym.isParameter();
default:
return false;
}