diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index f962710f5d8..4508ca0a291 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -425,14 +425,7 @@ public class ClassCodegen { null); mv.visitCode(); InstructionAdapter v = new InstructionAdapter(mv); - String owner = JetTypeMapper.jvmNameForImplementation(descriptor); - if (descriptor.getTypeConstructor().getParameters().size() > 0) { - v.load(0, JetTypeMapper.TYPE_OBJECT); - v.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - } - else { - v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - } + ExpressionCodegen.loadTypeInfo(descriptor, v); v.areturn(JetTypeMapper.TYPE_TYPEINFO); mv.visitMaxs(0, 0); mv.visitEnd(); diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 4767cf6d25d..5a08b679067 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -76,6 +76,17 @@ public class ExpressionCodegen extends JetVisitor { this.bindingContext = bindingContext; } + static void loadTypeInfo(ClassDescriptor descriptor, InstructionAdapter v) { + String owner = JetTypeMapper.jvmNameForImplementation(descriptor); + if (descriptor.getTypeConstructor().getParameters().size() > 0) { + v.load(0, JetTypeMapper.TYPE_OBJECT); + v.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + } + else { + v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + } + } + private void gen(JetElement expr) { if (expr == null) throw new CompilationException(); expr.accept(this); @@ -1301,7 +1312,7 @@ public class ExpressionCodegen extends JetVisitor { throw new UnsupportedOperationException("don't know how to handle non-class types in is"); } if (jetType.getArguments().size() > 0) { - newTypeInfo(jetType); + generateTypeInfo(jetType); gen(expression.getLeftHandSide(), OBJECT_TYPE); v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z"); } @@ -1314,11 +1325,23 @@ public class ExpressionCodegen extends JetVisitor { myStack.push(expression.isNot() ? StackValue.not(value) : value); } - private void newTypeInfo(JetType jetType) { + private void generateTypeInfo(JetType jetType) { + DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor(); + if (declarationDescriptor instanceof TypeParameterDescriptor) { + DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration(); + if (containingDeclaration == contextType && contextType instanceof ClassDescriptor) { + int index = indexOfTypeParameter((ClassDescriptor) contextType, (TypeParameterDescriptor) declarationDescriptor); + loadTypeInfo((ClassDescriptor) contextType, v); + v.iconst(index); + v.invokevirtual("jet/typeinfo/TypeInfo", "getTypeParameter", "(I)Ljet/typeinfo/TypeInfo;"); + return; + } + throw new UnsupportedOperationException("don't know what this type parameter resolves to"); + } + v.anew(JetTypeMapper.TYPE_TYPEINFO); v.dup(); - - v.aconst(typeMapper.jvmType((ClassDescriptor) jetType.getConstructor().getDeclarationDescriptor(), OwnerKind.INTERFACE)); + v.aconst(typeMapper.jvmType((ClassDescriptor) declarationDescriptor, OwnerKind.INTERFACE)); List arguments = jetType.getArguments(); if (arguments.size() > 0) { v.iconst(arguments.size()); @@ -1328,7 +1351,7 @@ public class ExpressionCodegen extends JetVisitor { TypeProjection argument = arguments.get(i); v.dup(); v.iconst(i); - newTypeInfo(argument.getType()); + generateTypeInfo(argument.getType()); v.astore(JetTypeMapper.TYPE_OBJECT); } v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V"); @@ -1338,6 +1361,15 @@ public class ExpressionCodegen extends JetVisitor { } } + private int indexOfTypeParameter(ClassDescriptor classDescriptor, TypeParameterDescriptor typeParameterDescriptor) { + List parameters = classDescriptor.getTypeConstructor().getParameters(); + int index = parameters.indexOf(typeParameterDescriptor); + if (index < 0) { + throw new UnsupportedOperationException("can't find type parameter index"); + } + return index; + } + private static class CompilationException extends RuntimeException { } } diff --git a/idea/testData/codegen/typeInfo/isWithGenericParameters.jet b/idea/testData/codegen/typeInfo/isWithGenericParameters.jet new file mode 100644 index 00000000000..d0bdd851ffc --- /dev/null +++ b/idea/testData/codegen/typeInfo/isWithGenericParameters.jet @@ -0,0 +1,8 @@ +class Wrapper() { + fun isSameWrapper(wrapper: Any) = wrapper is Wrapper +} + +fun foo() { + val wrapper = new Wrapper() + return wrapper.isSameWrapper(new Wrapper()) +} diff --git a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index 998704da068..800973cf507 100644 --- a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -59,6 +59,12 @@ public class TypeInfoTest extends CodegenTestCase { assertFalse((Boolean) foo.invoke(null, newRunnable())); } + public void testIsWithGenericParameters() throws Exception { + loadFile(); + Method foo = generateFunction(); + assertFalse((Boolean) foo.invoke(null)); + } + private Runnable newRunnable() { return new Runnable() { @Override diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 5f80f501fe2..e29ec82bc22 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -47,6 +47,10 @@ public class TypeInfo implements JetObject { return true; } + public TypeInfo getTypeParameter(int index) { + return typeParameters[index]; + } + @Override public TypeInfo getTypeInfo() { if (typeInfo == null) {