Fix for KT-10137: Internal error: couldn't inline method call on lambda taking extension function parameter
#KT-10137 Fixed
This commit is contained in:
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -492,4 +493,22 @@ public class InlineCodegenUtil {
|
||||
public static boolean isThis0(String name) {
|
||||
return THIS$0.equals(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AbstractInsnNode getPrevMeaningful(@NotNull AbstractInsnNode node) {
|
||||
AbstractInsnNode result = node.getPrevious();
|
||||
while (result != null && !UtilKt.isMeaningful(result)) {
|
||||
result = result.getPrevious();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void removeInterval(@NotNull MethodNode node, @NotNull AbstractInsnNode startInc, @NotNull AbstractInsnNode endInc) {
|
||||
while (startInc != endInc) {
|
||||
AbstractInsnNode next = startInc.getNext();
|
||||
node.instructions.remove(startInc);
|
||||
startInc = next;
|
||||
}
|
||||
node.instructions.remove(startInc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.inline;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
@@ -440,11 +441,16 @@ public class MethodInliner {
|
||||
|
||||
if (sourceValue.insns.size() == 1) {
|
||||
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
||||
AbstractInsnNode processingInstruction = insnNode;
|
||||
|
||||
lambdaInfo = getLambdaIfExists(insnNode);
|
||||
if (insnNode.getOpcode() == Opcodes.SWAP) {
|
||||
processingInstruction = InlineCodegenUtil.getPrevMeaningful(insnNode);
|
||||
}
|
||||
lambdaInfo = getLambdaIfExists(processingInstruction);
|
||||
if (lambdaInfo != null) {
|
||||
//remove inlinable access
|
||||
node.instructions.remove(insnNode);
|
||||
assert processingInstruction != null;
|
||||
InlineCodegenUtil.removeInterval(node, processingInstruction, insnNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,7 +552,12 @@ public class MethodInliner {
|
||||
return inliningContext.typeMapping.containsKey(owner);
|
||||
}
|
||||
|
||||
public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) {
|
||||
@Nullable
|
||||
public LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
|
||||
if (insnNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (insnNode.getOpcode() == Opcodes.ALOAD) {
|
||||
int varIndex = ((VarInsnNode) insnNode).var;
|
||||
return getLambdaIfExists(varIndex);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
W("OK").safe {
|
||||
result = this as String
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
class W(val value: Any)
|
||||
|
||||
inline fun W.safe(crossinline body : Any.() -> Unit) {
|
||||
{
|
||||
this.value?.body()
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
W("OK").safe {
|
||||
{
|
||||
result = this as String
|
||||
}()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
class W(val value: Any)
|
||||
|
||||
inline fun W.safe(crossinline body : Any.() -> Unit) {
|
||||
{
|
||||
this.value?.body()
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
W("OK").safe {
|
||||
result = this as String
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class W(val value: Any)
|
||||
|
||||
inline fun W.safe(body : Any.() -> Unit) {
|
||||
this.value?.body()
|
||||
}
|
||||
|
||||
+18
@@ -151,6 +151,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCall.1.kt")
|
||||
public void testSafeCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/safeCall.1.kt");
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCall_2.1.kt")
|
||||
public void testSafeCall_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/safeCall_2.1.kt");
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/properRecapturing")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1321,6 +1333,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCall.1.kt")
|
||||
public void testSafeCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/safeCall.1.kt");
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("severalClosures.1.kt")
|
||||
public void testSeveralClosures() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/severalClosures.1.kt");
|
||||
|
||||
+18
@@ -151,6 +151,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCall.1.kt")
|
||||
public void testSafeCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/safeCall.1.kt");
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCall_2.1.kt")
|
||||
public void testSafeCall_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/safeCall_2.1.kt");
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/properRecapturing")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1321,6 +1333,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("safeCall.1.kt")
|
||||
public void testSafeCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/safeCall.1.kt");
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("severalClosures.1.kt")
|
||||
public void testSeveralClosures() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/severalClosures.1.kt");
|
||||
|
||||
Reference in New Issue
Block a user