Skip inline lambdas in 'InlineCallSite' parameter calculation; Fix for KT-10679: Wrong outer after inline
#KT-10679 Fixed
This commit is contained in:
@@ -23,10 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
|
|
||||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
|
||||||
import org.jetbrains.kotlin.codegen.context.PackageContext;
|
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
@@ -307,8 +304,17 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private InlineCallSiteInfo getInlineCallSiteInfo() {
|
private InlineCallSiteInfo getInlineCallSiteInfo() {
|
||||||
MemberCodegen<?> parentCodegen = codegen.getParentCodegen();
|
|
||||||
MethodContext context = codegen.getContext();
|
MethodContext context = codegen.getContext();
|
||||||
|
MemberCodegen<?> parentCodegen = codegen.getParentCodegen();
|
||||||
|
while (context instanceof InlineLambdaContext) {
|
||||||
|
CodegenContext closureContext = context.getParentContext();
|
||||||
|
assert closureContext instanceof ClosureContext : "Parent context of inline lambda should be closure context";
|
||||||
|
assert closureContext.getParentContext() instanceof MethodContext : "Closure context should appear in method context";
|
||||||
|
context = (MethodContext) closureContext.getParentContext();
|
||||||
|
assert parentCodegen instanceof FakeMemberCodegen : "Parent codegen of inlined lambda should be FakeMemberCodegen";
|
||||||
|
parentCodegen = ((FakeMemberCodegen) parentCodegen).delegate;
|
||||||
|
}
|
||||||
|
|
||||||
JvmMethodSignature signature = typeMapper.mapSignature(context.getFunctionDescriptor(), context.getContextKind());
|
JvmMethodSignature signature = typeMapper.mapSignature(context.getFunctionDescriptor(), context.getContextKind());
|
||||||
return new InlineCallSiteInfo(parentCodegen.getClassName(), signature.getAsmMethod().getName(), signature.getAsmMethod().getDescriptor());
|
return new InlineCallSiteInfo(parentCodegen.getClassName(), signature.getAsmMethod().getName(), signature.getAsmMethod().getDescriptor());
|
||||||
}
|
}
|
||||||
@@ -389,7 +395,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
private static class FakeMemberCodegen extends MemberCodegen {
|
private static class FakeMemberCodegen extends MemberCodegen {
|
||||||
|
|
||||||
private final MemberCodegen delegate;
|
@NotNull final MemberCodegen delegate;
|
||||||
@NotNull private final String className;
|
@NotNull private final String className;
|
||||||
|
|
||||||
public FakeMemberCodegen(@NotNull MemberCodegen wrapped, @NotNull KtElement declaration, @NotNull FieldOwnerContext codegenContext, @NotNull String className) {
|
public FakeMemberCodegen(@NotNull MemberCodegen wrapped, @NotNull KtElement declaration, @NotNull FieldOwnerContext codegenContext, @NotNull String className) {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val res = call {
|
||||||
|
{ "OK" }
|
||||||
|
}
|
||||||
|
|
||||||
|
var enclosingMethod = res.javaClass.enclosingMethod
|
||||||
|
if (enclosingMethod?.name != "box") return "fail 1: ${enclosingMethod?.name}"
|
||||||
|
|
||||||
|
var enclosingClass = res.javaClass.enclosingClass
|
||||||
|
if (enclosingClass?.name != "AnonymousInLambda_1Kt") return "fail 2: ${enclosingClass?.name}"
|
||||||
|
|
||||||
|
return res()
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <R> call(s: () -> R) = s()
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val res = call {
|
||||||
|
test { "OK" }
|
||||||
|
}
|
||||||
|
|
||||||
|
var enclosingMethod = res.javaClass.enclosingMethod
|
||||||
|
if (enclosingMethod?.name != "box") return "fail 1: ${enclosingMethod?.name}"
|
||||||
|
|
||||||
|
var enclosingClass = res.javaClass.enclosingClass
|
||||||
|
if (enclosingClass?.name != "InlineChain_1Kt") return "fail 2: ${enclosingClass?.name}"
|
||||||
|
|
||||||
|
val res2 = call {
|
||||||
|
call {
|
||||||
|
test { "OK" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enclosingMethod = res2.javaClass.enclosingMethod
|
||||||
|
if (enclosingMethod?.name != "box") return "fail 1: ${enclosingMethod?.name}"
|
||||||
|
|
||||||
|
enclosingClass = res2.javaClass.enclosingClass
|
||||||
|
if (enclosingClass?.name != "InlineChain_1Kt") return "fail 2: ${enclosingClass?.name}"
|
||||||
|
|
||||||
|
return res2()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <R> call(s: () -> R) = s()
|
||||||
|
|
||||||
|
inline fun test(crossinline z: () -> String) = { z() }
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val res = call {
|
||||||
|
test { "OK" }
|
||||||
|
}
|
||||||
|
|
||||||
|
var enclosingMethod = res.javaClass.enclosingMethod
|
||||||
|
if (enclosingMethod?.name != "invoke") return "fail 1: ${enclosingMethod?.name}"
|
||||||
|
|
||||||
|
var enclosingClass = res.javaClass.enclosingClass
|
||||||
|
if (enclosingClass?.name != "InlineChain2_1Kt\$box$\$inlined\$call$1") return "fail 2: ${enclosingClass?.name}"
|
||||||
|
|
||||||
|
val res2 = call {
|
||||||
|
call {
|
||||||
|
test { "OK" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enclosingMethod = res2.javaClass.enclosingMethod
|
||||||
|
if (enclosingMethod?.name != "invoke") return "fail 1: ${enclosingMethod?.name}"
|
||||||
|
|
||||||
|
enclosingClass = res2.javaClass.enclosingClass
|
||||||
|
if (enclosingClass?.name != "InlineChain2_1Kt\$box$\$inlined\$call\$lambda\$lambda$2") return "fail 2: ${enclosingClass?.name}"
|
||||||
|
|
||||||
|
return res2()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <R> call(crossinline s: () -> R) = { s() }()
|
||||||
|
|
||||||
|
inline fun test(crossinline z: () -> String) = { z() }
|
||||||
+18
@@ -595,6 +595,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enclosingInfo"), Pattern.compile("^(.+)\\.1.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enclosingInfo"), Pattern.compile("^(.+)\\.1.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousInLambda.1.kt")
|
||||||
|
public void testAnonymousInLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/anonymousInLambda.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineChain.1.kt")
|
||||||
|
public void testInlineChain() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/inlineChain.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineChain2.1.kt")
|
||||||
|
public void testInlineChain2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/inlineChain2.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("objectInInlineFun.1.kt")
|
@TestMetadata("objectInInlineFun.1.kt")
|
||||||
public void testObjectInInlineFun() throws Exception {
|
public void testObjectInInlineFun() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/objectInInlineFun.1.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/objectInInlineFun.1.kt");
|
||||||
|
|||||||
+18
@@ -595,6 +595,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enclosingInfo"), Pattern.compile("^(.+)\\.1.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enclosingInfo"), Pattern.compile("^(.+)\\.1.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousInLambda.1.kt")
|
||||||
|
public void testAnonymousInLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/anonymousInLambda.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineChain.1.kt")
|
||||||
|
public void testInlineChain() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/inlineChain.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineChain2.1.kt")
|
||||||
|
public void testInlineChain2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/inlineChain2.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("objectInInlineFun.1.kt")
|
@TestMetadata("objectInInlineFun.1.kt")
|
||||||
public void testObjectInInlineFun() throws Exception {
|
public void testObjectInInlineFun() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/objectInInlineFun.1.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enclosingInfo/objectInInlineFun.1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user