generate CHECK_CAST for smartcasted 'this'

This commit is contained in:
Svetlana Isakova
2014-01-21 13:37:36 +04:00
parent 9ed57a5767
commit 9d493b6f7b
5 changed files with 43 additions and 8 deletions
@@ -293,7 +293,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitSuperExpression(@NotNull JetSuperExpression expression, StackValue data) {
return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true);
return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true, true);
}
private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
@@ -1720,7 +1720,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
StackValue script = StackValue.thisOrOuter(this, scriptClass, false);
StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false);
script.put(script.type, v);
Type fieldType = typeMapper.mapType(valueParameterDescriptor);
return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false);
@@ -2152,7 +2152,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
StackValue.onStack(exprType).put(type, v);
}
else {
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v);
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false, false).put(type, v);
}
}
else if (descriptor instanceof ScriptReceiver) {
@@ -3418,7 +3418,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) {
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false);
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true);
}
else {
if (descriptor instanceof CallableDescriptor) {
@@ -309,10 +309,11 @@ public abstract class StackValue {
return new Composed(prefix, suffix);
}
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper) {
// Coerce this/super for traits to support traits with required classes
// Do not coerce for other classes due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints)
boolean coerceType = descriptor.getKind() == ClassKind.TRAIT;
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper, boolean isExplicit) {
// Coerce this/super for traits to support traits with required classes.
// Coerce explicit 'this' for the case when it is smartcasted.
// Do not coerce for other classes due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints).
boolean coerceType = descriptor.getKind() == ClassKind.TRAIT || (isExplicit && !isSuper);
return new ThisOuter(codegen, descriptor, isSuper, coerceType);
}
@@ -0,0 +1,13 @@
open class A
class B : A() {
fun foo(i: Int) = i
}
fun A.test() = if (this is B) foo(42) else 0
fun box(): String {
if (B().test() != 42) return "fail1"
if (A().test() != 0) return "fail2"
return "OK"
}
@@ -0,0 +1,11 @@
package h
open class A {
fun bar() = if (this is B) this.foo() else "fail"
}
class B() : A() {
fun foo() = "OK"
}
fun box() = B().bar()
@@ -4979,6 +4979,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/typeInfo/asInLoop.kt");
}
@TestMetadata("implicitSmartCastedThis.kt")
public void testImplicitSmartCastedThis() throws Exception {
doTest("compiler/testData/codegen/box/typeInfo/implicitSmartCastedThis.kt");
}
@TestMetadata("inheritance.kt")
public void testInheritance() throws Exception {
doTest("compiler/testData/codegen/box/typeInfo/inheritance.kt");
@@ -4999,6 +5004,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/typeInfo/primitiveTypeInfo.kt");
}
@TestMetadata("smartCastedThis.kt")
public void testSmartCastedThis() throws Exception {
doTest("compiler/testData/codegen/box/typeInfo/smartCastedThis.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/typeMapping")