From c4954ebcc34f1c0179979150a9959857aba497fe Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 13 May 2011 19:07:51 +0200 Subject: [PATCH] 'as?' works on types with generics --- .../jet/codegen/ExpressionCodegen.java | 28 +++++++++++-------- .../codegen/typeInfo/asSafeWithGenerics.jet | 8 ++++++ .../jetbrains/jet/codegen/TypeInfoTest.java | 6 ++++ 3 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 idea/testData/codegen/typeInfo/asSafeWithGenerics.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index a8db4e34835..c0215d202e7 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1268,9 +1268,6 @@ public class ExpressionCodegen extends JetVisitor { else { JetTypeReference typeReference = expression.getRight(); JetType jetType = bindingContext.resolveTypeReference(typeReference); - if (jetType.getArguments().size() > 0) { - throw new UnsupportedOperationException("don't know how to handle type arguments in as/as?"); - } DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); if (!(descriptor instanceof ClassDescriptor)) { throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?"); @@ -1278,8 +1275,7 @@ public class ExpressionCodegen extends JetVisitor { Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE); gen(expression.getLeft(), OBJECT_TYPE); if (opToken == JetTokens.AS_SAFE) { - v.dup(); - v.instanceOf(type); + generateInstanceOf(expression.getLeft(), jetType, true); Label isInstance = new Label(); v.ifne(isInstance); v.pop(); @@ -1288,7 +1284,7 @@ public class ExpressionCodegen extends JetVisitor { myStack.push(StackValue.onStack(type)); } else { - throw new UnsupportedOperationException("as not yet implemented"); + throw new UnsupportedOperationException("'as' not yet implemented"); } } } @@ -1307,22 +1303,32 @@ public class ExpressionCodegen extends JetVisitor { } JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference(); JetType jetType = bindingContext.resolveTypeReference(typeReference); + generateInstanceOf(expression.getLeftHandSide(), jetType, false); + StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); + myStack.push(expression.isNot() ? StackValue.not(value) : value); + } + + private void generateInstanceOf(JetExpression expression, JetType jetType, boolean leaveExpressionOnStack) { DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); if (!(descriptor instanceof ClassDescriptor)) { - throw new UnsupportedOperationException("don't know how to handle non-class types in is"); + throw new UnsupportedOperationException("don't know how to handle non-class types"); } if (jetType.getArguments().size() > 0) { generateTypeInfo(jetType); - gen(expression.getLeftHandSide(), OBJECT_TYPE); + gen(expression, OBJECT_TYPE); + if (leaveExpressionOnStack) { + v.dupX1(); + } v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z"); } else { - gen(expression.getLeftHandSide(), OBJECT_TYPE); + gen(expression, OBJECT_TYPE); + if (leaveExpressionOnStack) { + v.dup(); + } Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE); v.instanceOf(type); } - StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); - myStack.push(expression.isNot() ? StackValue.not(value) : value); } private void generateTypeInfo(JetType jetType) { diff --git a/idea/testData/codegen/typeInfo/asSafeWithGenerics.jet b/idea/testData/codegen/typeInfo/asSafeWithGenerics.jet new file mode 100644 index 00000000000..8d521b5c260 --- /dev/null +++ b/idea/testData/codegen/typeInfo/asSafeWithGenerics.jet @@ -0,0 +1,8 @@ +class Wrapper() { + fun castToSelf(wrapper: Any) = wrapper as? Wrapper +} + +fun foo() { + val wrapper = new Wrapper() + return wrapper.castToSelf(new Wrapper()) +} diff --git a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index 800973cf507..b34f95aaef1 100644 --- a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -65,6 +65,12 @@ public class TypeInfoTest extends CodegenTestCase { assertFalse((Boolean) foo.invoke(null)); } + public void testAsSafeWithGenerics() throws Exception { + loadFile(); + Method foo = generateFunction(); + assertNull(foo.invoke(null)); + } + private Runnable newRunnable() { return new Runnable() { @Override