store nullability information in TypeInfo

This commit is contained in:
Dmitry Jemerov
2011-06-30 17:46:52 +02:00
parent 01a08ecd04
commit 840f9ffef1
6 changed files with 44 additions and 17 deletions
@@ -49,10 +49,11 @@ public class ClassCodegen {
}
public static void newTypeInfo(InstructionAdapter v, Type asmType) {
public static void newTypeInfo(InstructionAdapter v, boolean isNullable, Type asmType) {
v.anew(JetTypeMapper.TYPE_TYPEINFO);
v.dup();
v.aconst(asmType);
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;)V");
v.aconst(isNullable);
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z)V");
}
}
@@ -1453,7 +1453,7 @@ public class ExpressionCodegen extends JetVisitor {
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
JetType typeArgument = bindingContext.resolveTypeReference(jetTypeArgument.getTypeReference());
// TODO is the makeNullable() call correct here?
ClassCodegen.newTypeInfo(v, typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
ClassCodegen.newTypeInfo(v, typeArgument.isNullable(), typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
}
v.invokespecial(JetTypeMapper.jvmNameForImplementation(classDecl), "<init>", method.getDescriptor());
@@ -1724,6 +1724,7 @@ public class ExpressionCodegen extends JetVisitor {
v.anew(JetTypeMapper.TYPE_TYPEINFO);
v.dup();
v.aconst(jvmType);
v.aconst(jetType.isNullable());
List<TypeProjection> arguments = jetType.getArguments();
if (arguments.size() > 0) {
v.iconst(arguments.size());
@@ -1736,10 +1737,10 @@ public class ExpressionCodegen extends JetVisitor {
generateTypeInfo(argument.getType());
v.astore(JetTypeMapper.TYPE_OBJECT);
}
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V");
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V");
}
else {
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;)V");
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z)V");
}
}
@@ -318,6 +318,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.dup();
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE));
iv.aconst(false);
iv.iconst(typeParamCount);
iv.newarray(JetTypeMapper.TYPE_TYPEINFO);
@@ -327,7 +328,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
iv.astore(JetTypeMapper.TYPE_OBJECT);
}
iv.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V");
iv.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V");
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
@@ -394,7 +395,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (needTypeInfo) {
JetTypeMapper typeMapper = state.getTypeMapper();
ClassCodegen.newTypeInfo(v, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE));
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE));
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
if (needInstance) {
@@ -0,0 +1,13 @@
class Box<T>(t: T) {
var value = t
}
fun box(): String {
val nullableBox = Box<String?>("")
val notnullBox = Box<String>("")
if (nullableBox is Box<String>) return "fail 1"
if (notnullBox is Box<String?>) return "fail 2"
if (nullableBox !is Box<String?>) return "fail 3"
if (notnullBox !is Box<String>) return "fail 4"
return "OK"
}
@@ -88,6 +88,10 @@ public class TypeInfoTest extends CodegenTestCase {
blackBoxFile("typeInfo/primitiveTypeInfo.jet");
}
public void testNullability() throws Exception {
blackBoxFile("typeInfo/nullability.jet");
}
private Runnable newRunnable() {
return new Runnable() {
@Override
+17 -10
View File
@@ -10,15 +10,18 @@ import java.util.Arrays;
public class TypeInfo<T> implements JetObject {
private TypeInfo<?> typeInfo;
private final Class<T> theClass;
private final boolean nullable;
private final TypeInfo[] typeParameters;
public TypeInfo(Class<T> theClass) {
public TypeInfo(Class<T> theClass, boolean nullable) {
this.theClass = theClass;
this.nullable = nullable;
this.typeParameters = null;
}
public TypeInfo(Class<T> theClass, TypeInfo[] typeParameters) {
public TypeInfo(Class<T> theClass, boolean nullable, TypeInfo[] typeParameters) {
this.theClass = theClass;
this.nullable = nullable;
this.typeParameters = typeParameters;
}
@@ -33,6 +36,9 @@ public class TypeInfo<T> implements JetObject {
if (!theClass.isAssignableFrom(other.theClass)) {
return false;
}
if (nullable != other.nullable) {
return false;
}
if (typeParameters != null) {
if (other.typeParameters == null || other.typeParameters.length != typeParameters.length) {
throw new IllegalArgumentException("inconsistent type infos for the same class");
@@ -68,6 +74,7 @@ public class TypeInfo<T> implements JetObject {
TypeInfo typeInfo = (TypeInfo) o;
if (!theClass.equals(typeInfo.theClass)) return false;
if (nullable != typeInfo.nullable) return false;
if (!Arrays.equals(typeParameters, typeInfo.typeParameters)) return false;
return true;
@@ -80,12 +87,12 @@ public class TypeInfo<T> implements JetObject {
return result;
}
public static final TypeInfo<Byte> BYTE_TYPE_INFO = new TypeInfo<Byte>(Byte.class);
public static final TypeInfo<Short> SHORT_TYPE_INFO = new TypeInfo<Short>(Short.class);
public static final TypeInfo<Integer> INT_TYPE_INFO = new TypeInfo<Integer>(Integer.class);
public static final TypeInfo<Long> LONG_TYPE_INFO = new TypeInfo<Long>(Long.class);
public static final TypeInfo<Character> CHAR_TYPE_INFO = new TypeInfo<Character>(Character.class);
public static final TypeInfo<Boolean> BOOL_TYPE_INFO = new TypeInfo<Boolean>(Boolean.class);
public static final TypeInfo<Float> FLOAT_TYPE_INFO = new TypeInfo<Float>(Float.class);
public static final TypeInfo<Double> DOUBLE_TYPE_INFO = new TypeInfo<Double>(Double.class);
public static final TypeInfo<Byte> BYTE_TYPE_INFO = new TypeInfo<Byte>(Byte.class, false);
public static final TypeInfo<Short> SHORT_TYPE_INFO = new TypeInfo<Short>(Short.class, false);
public static final TypeInfo<Integer> INT_TYPE_INFO = new TypeInfo<Integer>(Integer.class, false);
public static final TypeInfo<Long> LONG_TYPE_INFO = new TypeInfo<Long>(Long.class, false);
public static final TypeInfo<Character> CHAR_TYPE_INFO = new TypeInfo<Character>(Character.class, false);
public static final TypeInfo<Boolean> BOOL_TYPE_INFO = new TypeInfo<Boolean>(Boolean.class, false);
public static final TypeInfo<Float> FLOAT_TYPE_INFO = new TypeInfo<Float>(Float.class, false);
public static final TypeInfo<Double> DOUBLE_TYPE_INFO = new TypeInfo<Double>(Double.class, false);
}