diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 8c74d403175..dfd72db5e8f 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -608,7 +608,9 @@ public class ExpressionCodegen extends JetVisitor { else { boolean isStatic = container instanceof NamespaceDescriptorImpl; final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; - final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField); + JetExpression receiver = getReceiverForSelector(expression); + final boolean forceInterface = receiver != null && !(receiver instanceof JetThisExpression); + final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface); if (!isStatic) { ensureReceiverOnStack(expression, container instanceof ClassDescriptor ? (ClassDescriptor) container : null); } @@ -621,14 +623,14 @@ public class ExpressionCodegen extends JetVisitor { } } - public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) { + public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface) { DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl; final JetType outType = propertyDescriptor.getOutType(); - boolean isInsideClass = containingDeclaration == contextType; + boolean isInsideClass = !forceInterface && containingDeclaration == contextType; Method getter; Method setter; - if (directToField) { + if (forceField) { getter = null; setter = null; } @@ -771,13 +773,21 @@ public class ExpressionCodegen extends JetVisitor { } } - private void ensureReceiverOnStack(JetElement expression, @Nullable ClassDescriptor calleeContainingClass) { + private JetExpression getReceiverForSelector(JetElement expression) { if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); - if (!resolvesToClassOrPackage(parent.getReceiverExpression())) { + return parent.getReceiverExpression(); + } + return null; + } + + private void ensureReceiverOnStack(JetElement expression, @Nullable ClassDescriptor calleeContainingClass) { + JetExpression receiver = getReceiverForSelector(expression); + if (receiver != null) { + if (!resolvesToClassOrPackage(receiver)) { // we have a receiver on stack if (myStack.isEmpty()) { - throw new IllegalStateException("expected receiver on stack but it's not there: " + parent.getReceiverExpression().getText()); + throw new IllegalStateException("expected receiver on stack but it's not there: " + receiver.getText()); } myStack.pop().put(JetTypeMapper.TYPE_OBJECT, v); } @@ -1551,6 +1561,7 @@ public class ExpressionCodegen extends JetVisitor { throwNewException(CLASS_TYPE_CAST_EXCEPTION); } v.mark(isInstance); + v.checkcast(type); myStack.push(StackValue.onStack(type)); } } diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 62a252d7c80..90fd8d00c4f 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -298,7 +298,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (initializer != null) { iv.load(0, JetTypeMapper.TYPE_OBJECT); codegen.genToJVMStack(initializer); - codegen.intermediateValueForProperty(propertyDescriptor, false).store(iv); + codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv); } } diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 1f95548c87a..e4c9af2102a 100644 --- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -89,7 +89,7 @@ public class NamespaceCodegen { if (initializer != null && !(initializer instanceof JetConstantExpression)) { final PropertyDescriptor descriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); codegen.genToJVMStack(initializer); - codegen.intermediateValueForProperty(descriptor, false).store(new InstructionAdapter(mv)); + codegen.intermediateValueForProperty(descriptor, false, false).store(new InstructionAdapter(mv)); } } } diff --git a/idea/testData/codegen/checkCast.jet b/idea/testData/codegen/checkCast.jet new file mode 100644 index 00000000000..5615533f317 --- /dev/null +++ b/idea/testData/codegen/checkCast.jet @@ -0,0 +1,15 @@ +class C(val x: Int) { + fun equals(rhs: Any?): Boolean { + if (rhs is C) { + val rhsC = rhs as C + return rhsC.x == x + } + return false + } +} + +fun box(): String { + val c1 = C(10) + val c2 = C(10) + return if (c1 == c2) "OK" else "fail" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index cc597b51ca2..dc2c1eb6c32 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -404,4 +404,8 @@ public class NamespaceGenTest extends CodegenTestCase { public void testNamespaceQualifiedMethod() throws Exception { blackBoxFile("namespaceQualifiedMethod.jet"); } + + public void testCheckCast() throws Exception { + blackBoxFile("checkCast.jet"); + } }