From 1040c97196d5eb733e89b026c0447acaf184c382 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 20 Dec 2016 17:48:46 +0100 Subject: [PATCH] Fix for: KT-14011 Compiler crash when inlining: lateinit property allRecapturedParameters has not been initialized #KT-14011 Fixed --- .../inline/AnonymousObjectTransformer.java | 2 +- .../kotlin/codegen/inline/InlineCodegen.java | 2 +- .../kotlin/codegen/inline/InlineResult.kt | 20 +++++++++++---- .../kotlin/codegen/inline/MethodInliner.java | 9 ++++--- .../codegen/inline/TransformationInfo.kt | 7 ++++++ .../boxInline/anonymousObject/kt14011.kt | 21 ++++++++++++++++ .../boxInline/anonymousObject/kt14011_2.kt | 21 ++++++++++++++++ .../boxInline/anonymousObject/kt14011_3.kt | 25 +++++++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 18 +++++++++++++ ...otlinAgainstInlineKotlinTestGenerated.java | 18 +++++++++++++ 10 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt14011.kt create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt14011_2.kt create mode 100644 compiler/testData/codegen/boxInline/anonymousObject/kt14011_3.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index 2572803b05c..cae91e53983 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -193,7 +193,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer() private val classesToRemove = HashSet() private val changedTypes = HashMap() val reifiedTypeParametersUsages = ReifiedTypeParametersUsages() - fun addAllClassesToRemove(child: InlineResult): InlineResult { - classesToRemove.addAll(child.classesToRemove) - return this + fun merge(child: InlineResult) { + classesToRemove.addAll(child.calcClassesToRemove()) + } + + fun mergeWithNotChangeInfo(child: InlineResult) { + notChangedTypes.addAll(child.notChangedTypes) + merge(child) } fun addClassToRemove(classInternalName: String) { classesToRemove.add(classInternalName) } + fun addNotChangedClass(classInternalName: String) { + notChangedTypes.add(classInternalName) + } + fun addChangedType(oldClassInternalName: String, newClassInternalName: String) { changedTypes.put(oldClassInternalName, newClassInternalName) } - fun getClassesToRemove(): Set { - return classesToRemove + + fun calcClassesToRemove(): Set { + return classesToRemove - notChangedTypes } fun getChangedTypes(): Map { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index 67758a7904a..d62fdc6e3a8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -164,9 +164,9 @@ public class MethodInliner { private void handleAnonymousObjectRegeneration() { transformationInfo = iterator.next(); + String oldClassName = transformationInfo.getOldClassName(); if (transformationInfo.shouldRegenerate(isSameModule)) { //TODO: need poping of type but what to do with local funs??? - String oldClassName = transformationInfo.getOldClassName(); String newClassName = transformationInfo.getNewClassName(); remapper.addMapping(oldClassName, newClassName); @@ -178,7 +178,7 @@ public class MethodInliner { ObjectTransformer transformer = transformationInfo.createTransformer(childInliningContext, isSameModule); InlineResult transformResult = transformer.doTransform(nodeRemapper); - result.addAllClassesToRemove(transformResult); + result.merge(transformResult); result.addChangedType(oldClassName, newClassName); if (inliningContext.isInliningLambda && transformationInfo.canRemoveAfterTransformation()) { @@ -191,6 +191,9 @@ public class MethodInliner { result.getReifiedTypeParametersUsages().mergeAll(transformResult.getReifiedTypeParametersUsages()); } } + else if (!transformationInfo.getWasAlreadyRegenerated()) { + result.addNotChangedClass(oldClassName); + } } @Override @@ -248,7 +251,7 @@ public class MethodInliner { LocalVarRemapper remapper = new LocalVarRemapper(lambdaParameters, valueParamShift); //TODO add skipped this and receiver InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift); - result.addAllClassesToRemove(lambdaResult); + result.mergeWithNotChangeInfo(lambdaResult); //return value boxing/unboxing Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor())); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt index 49dd41e5bb1..3fe22c83549 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt @@ -26,6 +26,10 @@ interface TransformationInfo { val nameGenerator: NameGenerator + val wasAlreadyRegenerated: Boolean + get() = false + + fun shouldRegenerate(sameModule: Boolean): Boolean fun canRemoveAfterTransformation(): Boolean @@ -77,6 +81,9 @@ class AnonymousObjectTransformationInfo internal constructor( lateinit var capturedLambdasToInline: Map + override val wasAlreadyRegenerated: Boolean + get() = alreadyRegenerated + constructor( ownerInternalName: String, needReification: Boolean, diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt14011.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt14011.kt new file mode 100644 index 00000000000..1e8e1ab579c --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt14011.kt @@ -0,0 +1,21 @@ +// FILE: 1.kt +package test + +inline fun inline1(crossinline action: () -> Unit) { + action(); + { action() }() +} + +inline fun inline2(crossinline action: () -> Unit) = { action() } + + +// FILE: 2.kt +import test.* + +var result = "fail" +fun box(): String { + inline1 { inline2 { result = "OK" }() } + + return result +} + diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt14011_2.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt14011_2.kt new file mode 100644 index 00000000000..3997d2aa02f --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt14011_2.kt @@ -0,0 +1,21 @@ +// FILE: 1.kt +package test + +inline fun inline1(crossinline action: () -> Unit) { + { action () } + action(); +} + +inline fun inline2(crossinline action: () -> Unit) = { action() } + + +// FILE: 2.kt +import test.* + +var result = "fail" +fun box(): String { + inline1 { inline2 { result ="OK" }() } + + return result +} + diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt14011_3.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt14011_3.kt new file mode 100644 index 00000000000..77cf8a653b5 --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt14011_3.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +package test + +inline fun inline1(crossinline action: () -> Unit) { + { action () } + action(); +} + +inline fun inline2(crossinline action: () -> Unit) = { + action() +} + + +// FILE: 2.kt +import test.* + +var result = "fail" +fun box(): String { + inline1 { + inline2 { { result ="OK" }() }() + } + + return result +} + diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index ff06d0bb37f..10203e7af3c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -140,6 +140,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTest(fileName); } + @TestMetadata("kt14011.kt") + public void testKt14011() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt14011.kt"); + doTest(fileName); + } + + @TestMetadata("kt14011_2.kt") + public void testKt14011_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt14011_2.kt"); + doTest(fileName); + } + + @TestMetadata("kt14011_3.kt") + public void testKt14011_3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt14011_3.kt"); + doTest(fileName); + } + @TestMetadata("kt6552.kt") public void testKt6552() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 5a0d992fdf2..7f2b555c832 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -140,6 +140,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doTest(fileName); } + @TestMetadata("kt14011.kt") + public void testKt14011() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt14011.kt"); + doTest(fileName); + } + + @TestMetadata("kt14011_2.kt") + public void testKt14011_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt14011_2.kt"); + doTest(fileName); + } + + @TestMetadata("kt14011_3.kt") + public void testKt14011_3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt14011_3.kt"); + doTest(fileName); + } + @TestMetadata("kt6552.kt") public void testKt6552() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");