From 840f9ffef1d7af4403800b6e29e806c46e4073c6 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 30 Jun 2011 17:46:52 +0200 Subject: [PATCH] store nullability information in TypeInfo --- .../jetbrains/jet/codegen/ClassCodegen.java | 5 ++-- .../jet/codegen/ExpressionCodegen.java | 7 ++--- .../codegen/ImplementationBodyCodegen.java | 5 ++-- .../testData/codegen/typeInfo/nullability.jet | 13 +++++++++ .../jetbrains/jet/codegen/TypeInfoTest.java | 4 +++ stdlib/src/jet/typeinfo/TypeInfo.java | 27 ++++++++++++------- 6 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 idea/testData/codegen/typeInfo/nullability.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index e5314c7a80c..bc7e5b0a041 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -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", "", "(Ljava/lang/Class;)V"); + v.aconst(isNullable); + v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z)V"); } } diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 443422e4b2e..51735604818 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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), "", 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 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", "", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V"); + v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V"); } else { - v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;)V"); + v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z)V"); } } diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 51106f271f0..2726c54b25a 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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", "", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V"); + iv.invokespecial("jet/typeinfo/TypeInfo", "", "(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) { diff --git a/idea/testData/codegen/typeInfo/nullability.jet b/idea/testData/codegen/typeInfo/nullability.jet new file mode 100644 index 00000000000..5ef65122d2b --- /dev/null +++ b/idea/testData/codegen/typeInfo/nullability.jet @@ -0,0 +1,13 @@ +class Box(t: T) { + var value = t +} + +fun box(): String { + val nullableBox = Box("") + val notnullBox = Box("") + if (nullableBox is Box) return "fail 1" + if (notnullBox is Box) return "fail 2" + if (nullableBox !is Box) return "fail 3" + if (notnullBox !is Box) return "fail 4" + return "OK" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index 4e831cd2984..79b950310aa 100644 --- a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -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 diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 4ff4f9c0c17..85f6829bf50 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -10,15 +10,18 @@ import java.util.Arrays; public class TypeInfo implements JetObject { private TypeInfo typeInfo; private final Class theClass; + private final boolean nullable; private final TypeInfo[] typeParameters; - public TypeInfo(Class theClass) { + public TypeInfo(Class theClass, boolean nullable) { this.theClass = theClass; + this.nullable = nullable; this.typeParameters = null; } - public TypeInfo(Class theClass, TypeInfo[] typeParameters) { + public TypeInfo(Class theClass, boolean nullable, TypeInfo[] typeParameters) { this.theClass = theClass; + this.nullable = nullable; this.typeParameters = typeParameters; } @@ -33,6 +36,9 @@ public class TypeInfo 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 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 implements JetObject { return result; } - public static final TypeInfo BYTE_TYPE_INFO = new TypeInfo(Byte.class); - public static final TypeInfo SHORT_TYPE_INFO = new TypeInfo(Short.class); - public static final TypeInfo INT_TYPE_INFO = new TypeInfo(Integer.class); - public static final TypeInfo LONG_TYPE_INFO = new TypeInfo(Long.class); - public static final TypeInfo CHAR_TYPE_INFO = new TypeInfo(Character.class); - public static final TypeInfo BOOL_TYPE_INFO = new TypeInfo(Boolean.class); - public static final TypeInfo FLOAT_TYPE_INFO = new TypeInfo(Float.class); - public static final TypeInfo DOUBLE_TYPE_INFO = new TypeInfo(Double.class); + public static final TypeInfo BYTE_TYPE_INFO = new TypeInfo(Byte.class, false); + public static final TypeInfo SHORT_TYPE_INFO = new TypeInfo(Short.class, false); + public static final TypeInfo INT_TYPE_INFO = new TypeInfo(Integer.class, false); + public static final TypeInfo LONG_TYPE_INFO = new TypeInfo(Long.class, false); + public static final TypeInfo CHAR_TYPE_INFO = new TypeInfo(Character.class, false); + public static final TypeInfo BOOL_TYPE_INFO = new TypeInfo(Boolean.class, false); + public static final TypeInfo FLOAT_TYPE_INFO = new TypeInfo(Float.class, false); + public static final TypeInfo DOUBLE_TYPE_INFO = new TypeInfo(Double.class, false); }