diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 5b090c5bcec..16afc8bc0a1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -157,8 +157,13 @@ public abstract class StackValue { } @NotNull - public static Local local(int index, @NotNull Type type, @NotNull VariableDescriptor descriptor) { - return new Local(index, type, descriptor.getType(), descriptor.isLateInit(), descriptor.getName()); + public static StackValue local(int index, @NotNull Type type, @NotNull VariableDescriptor descriptor) { + if (descriptor.isLateInit()) { + return new LateinitLocal(index, type, descriptor.getType(), descriptor.getName()); + } + else { + return new Local(index, type, descriptor.getType()); + } } @NotNull @@ -805,50 +810,65 @@ public abstract class StackValue { public static class Local extends StackValue { public final int index; - private final boolean isLateinit; - private final Name name; - private Local(int index, Type type, KotlinType kotlinType, boolean isLateinit, Name name) { + private Local(int index, Type type, KotlinType kotlinType) { super(type, kotlinType, false); if (index < 0) { throw new IllegalStateException("local variable index must be non-negative"); } - if (isLateinit && name == null) { - throw new IllegalArgumentException("Lateinit local variable should have name: #" + index + " " + type.getDescriptor()); - } - this.index = index; - this.isLateinit = isLateinit; - this.name = name; } private Local(int index, Type type) { - this(index, type, null, false, null); - } - - private Local(int index, Type type, KotlinType kotlinType) { - this(index, type, kotlinType, false, null); + this(index, type, null); } @Override public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) { v.load(index, this.type); - if (isLateinit) { - StackValue.genNonNullAssertForLateinit(v, name.asString()); - } coerceTo(type, kotlinType, v); - // TODO unbox } @Override public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) { coerceFrom(topOfStackType, topOfStackKotlinType, v); v.store(index, this.type); - if (isLateinit) { - PseudoInsnsKt.storeNotNull(v); + } + } + + public static class LateinitLocal extends StackValue { + public final int index; + private final Name name; + + private LateinitLocal(int index, Type type, KotlinType kotlinType, Name name) { + super(type, kotlinType, false); + + if (index < 0) { + throw new IllegalStateException("local variable index must be non-negative"); } + + if (name == null) { + throw new IllegalArgumentException("Lateinit local variable should have name: #" + index + " " + type.getDescriptor()); + } + + this.index = index; + this.name = name; + } + + @Override + public void putSelector(@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v) { + v.load(index, this.type); + StackValue.genNonNullAssertForLateinit(v, name.asString()); + coerceTo(type, kotlinType, v); + } + + @Override + public void storeSelector(@NotNull Type topOfStackType, @Nullable KotlinType topOfStackKotlinType, @NotNull InstructionAdapter v) { + coerceFrom(topOfStackType, topOfStackKotlinType, v); + v.store(index, this.type); + PseudoInsnsKt.storeNotNull(v); } } diff --git a/compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt b/compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt new file mode 100644 index 00000000000..422a501ba6d --- /dev/null +++ b/compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt @@ -0,0 +1,15 @@ +// WITH_RUNTIME + +fun box(): String { + lateinit var str: String + try { + println(str) + return "Should throw an exception" + } + catch (e: UninitializedPropertyAccessException) { + return "OK" + } + catch (e: Throwable) { + return "Unexpected exception: ${e::class}" + } +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index f1c48efdf14..0acddd57465 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13812,6 +13812,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/properties/lateinit/local/capturedLocalLateinit.kt"); } + @TestMetadata("kt23260.kt") + public void testKt23260() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt"); + doTest(fileName); + } + @TestMetadata("localLateinit.kt") public void testLocalLateinit() throws Exception { runTest("compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 75f3ec378eb..b62fb39af40 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13812,6 +13812,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/properties/lateinit/local/capturedLocalLateinit.kt"); } + @TestMetadata("kt23260.kt") + public void testKt23260() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt"); + doTest(fileName); + } + @TestMetadata("localLateinit.kt") public void testLocalLateinit() throws Exception { runTest("compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 4c6ab50731d..9f6d588878c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13812,6 +13812,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/properties/lateinit/local/capturedLocalLateinit.kt"); } + @TestMetadata("kt23260.kt") + public void testKt23260() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt"); + doTest(fileName); + } + @TestMetadata("localLateinit.kt") public void testLocalLateinit() throws Exception { runTest("compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 2694cedf142..007944e84a1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13202,6 +13202,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/properties/lateinit/local/capturedLocalLateinit.kt"); } + @TestMetadata("kt23260.kt") + public void testKt23260() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/lateinit/local/kt23260.kt"); + doTest(fileName); + } + @TestMetadata("localLateinit.kt") public void testLocalLateinit() throws Exception { runTest("compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt");