From 9d493b6f7b88f0361472618aa99cdb633725d208 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 21 Jan 2014 13:37:36 +0400 Subject: [PATCH] generate CHECK_CAST for smartcasted 'this' --- .../jetbrains/jet/codegen/ExpressionCodegen.java | 8 ++++---- .../src/org/jetbrains/jet/codegen/StackValue.java | 9 +++++---- .../codegen/box/typeInfo/implicitSmartCastedThis.kt | 13 +++++++++++++ .../codegen/box/typeInfo/smartCastedThis.kt | 11 +++++++++++ .../generated/BlackBoxCodegenTestGenerated.java | 10 ++++++++++ 5 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/codegen/box/typeInfo/implicitSmartCastedThis.kt create mode 100644 compiler/testData/codegen/box/typeInfo/smartCastedThis.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 96bfededdf0..cc1b7ad8911 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -293,7 +293,7 @@ public class ExpressionCodegen extends JetVisitor 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 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 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 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) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 532e3ca5852..a7df78b5aea 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -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); } diff --git a/compiler/testData/codegen/box/typeInfo/implicitSmartCastedThis.kt b/compiler/testData/codegen/box/typeInfo/implicitSmartCastedThis.kt new file mode 100644 index 00000000000..a4587005887 --- /dev/null +++ b/compiler/testData/codegen/box/typeInfo/implicitSmartCastedThis.kt @@ -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" +} diff --git a/compiler/testData/codegen/box/typeInfo/smartCastedThis.kt b/compiler/testData/codegen/box/typeInfo/smartCastedThis.kt new file mode 100644 index 00000000000..6ed06c50328 --- /dev/null +++ b/compiler/testData/codegen/box/typeInfo/smartCastedThis.kt @@ -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() \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 6ded8f412dc..684e45198a0 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -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")