'as?' works on types with generics
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user