'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 {
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) {
@@ -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));
}
public void testAsSafeWithGenerics() throws Exception {
loadFile();
Method foo = generateFunction();
assertNull(foo.invoke(null));
}
private Runnable newRunnable() {
return new Runnable() {
@Override