'as?' works on types with generics

This commit is contained in:
Dmitry Jemerov
2011-05-13 19:07:51 +02:00
parent ffd0119a46
commit c4954ebcc3
3 changed files with 31 additions and 11 deletions
@@ -1268,9 +1268,6 @@ public class ExpressionCodegen extends JetVisitor {
else { else {
JetTypeReference typeReference = expression.getRight(); JetTypeReference typeReference = expression.getRight();
JetType jetType = bindingContext.resolveTypeReference(typeReference); 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(); DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (!(descriptor instanceof ClassDescriptor)) { if (!(descriptor instanceof ClassDescriptor)) {
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?"); 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); Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE);
gen(expression.getLeft(), OBJECT_TYPE); gen(expression.getLeft(), OBJECT_TYPE);
if (opToken == JetTokens.AS_SAFE) { if (opToken == JetTokens.AS_SAFE) {
v.dup(); generateInstanceOf(expression.getLeft(), jetType, true);
v.instanceOf(type);
Label isInstance = new Label(); Label isInstance = new Label();
v.ifne(isInstance); v.ifne(isInstance);
v.pop(); v.pop();
@@ -1288,7 +1284,7 @@ public class ExpressionCodegen extends JetVisitor {
myStack.push(StackValue.onStack(type)); myStack.push(StackValue.onStack(type));
} }
else { 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(); JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
JetType jetType = bindingContext.resolveTypeReference(typeReference); 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(); DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (!(descriptor instanceof ClassDescriptor)) { 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) { if (jetType.getArguments().size() > 0) {
generateTypeInfo(jetType); 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"); v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z");
} }
else { else {
gen(expression.getLeftHandSide(), OBJECT_TYPE); gen(expression, OBJECT_TYPE);
if (leaveExpressionOnStack) {
v.dup();
}
Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE); Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE);
v.instanceOf(type); v.instanceOf(type);
} }
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
myStack.push(expression.isNot() ? StackValue.not(value) : value);
} }
private void generateTypeInfo(JetType jetType) { private void generateTypeInfo(JetType jetType) {
@@ -0,0 +1,8 @@
class Wrapper<T>() {
fun castToSelf(wrapper: Any) = wrapper as? Wrapper<T>
}
fun foo() {
val wrapper = new Wrapper<Int>()
return wrapper.castToSelf(new Wrapper<String>())
}
@@ -65,6 +65,12 @@ public class TypeInfoTest extends CodegenTestCase {
assertFalse((Boolean) foo.invoke(null)); assertFalse((Boolean) foo.invoke(null));
} }
public void testAsSafeWithGenerics() throws Exception {
loadFile();
Method foo = generateFunction();
assertNull(foo.invoke(null));
}
private Runnable newRunnable() { private Runnable newRunnable() {
return new Runnable() { return new Runnable() {
@Override @Override