JVM: do not reify methods of objects in lambdas
All type parameters used in them are not from the inline function anyway.
This commit is contained in:
+6
-6
@@ -295,7 +295,6 @@ class AnonymousObjectTransformer(
|
||||
capturedBuilder: ParametersBuilder,
|
||||
isConstructor: Boolean
|
||||
): InlineResult {
|
||||
val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
|
||||
val parameters =
|
||||
if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode)
|
||||
|
||||
@@ -304,7 +303,10 @@ class AnonymousObjectTransformer(
|
||||
transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor
|
||||
)
|
||||
|
||||
val inliner = MethodInliner(
|
||||
val reifiedTypeParametersUsages = if (inliningContext.shouldReifyTypeParametersInObjects)
|
||||
inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
|
||||
else null
|
||||
val result = MethodInliner(
|
||||
sourceNode,
|
||||
parameters,
|
||||
inliningContext.subInline(transformationInfo.nameGenerator),
|
||||
@@ -319,10 +321,8 @@ class AnonymousObjectTransformer(
|
||||
inliningContext.callSiteInfo.file,
|
||||
inliningContext.callSiteInfo.lineNumber
|
||||
), null
|
||||
)
|
||||
|
||||
val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
|
||||
result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify)
|
||||
).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
|
||||
reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll)
|
||||
deferringVisitor.visitMaxs(-1, -1)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -44,8 +44,16 @@ open class InliningContext(
|
||||
val lambdaInfo: LambdaInfo?,
|
||||
val classRegeneration: Boolean
|
||||
) {
|
||||
val isInliningLambda
|
||||
get() = lambdaInfo != null
|
||||
|
||||
val isInliningLambda = lambdaInfo != null
|
||||
// Consider this arrangement:
|
||||
// inline fun <reified T> f(x: () -> Unit = { /* uses `T` in a local class */ }) = x()
|
||||
// inline fun <reified V> g() = f<...> { /* uses `V` in a local class */ }
|
||||
// When inlining `f` into `g`, we need to reify the contents of the default for `x` (if it was used), but not the
|
||||
// contents of the lambda passed as the argument in `g` as all reified type parameters used by the latter are not from `f`.
|
||||
val shouldReifyTypeParametersInObjects: Boolean
|
||||
get() = lambdaInfo == null || lambdaInfo is DefaultLambda
|
||||
|
||||
var generateAssertField = false
|
||||
|
||||
@@ -54,7 +62,8 @@ open class InliningContext(
|
||||
|
||||
var isContinuation: Boolean = false
|
||||
|
||||
val isRoot: Boolean = parent == null
|
||||
val isRoot: Boolean
|
||||
get() = parent == null
|
||||
|
||||
val root: RootInliningContext
|
||||
get() = if (isRoot) this as RootInliningContext else parent!!.root
|
||||
|
||||
@@ -318,14 +318,8 @@ class MethodInliner(
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
||||
}
|
||||
} else if (ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) {
|
||||
// Consider this arrangement:
|
||||
// inline fun <reified T> f(x: () -> Unit = { /* uses `T` in a local class */ }) = x()
|
||||
// inline fun <reified V> g() = f<...> { /* uses `V` in a local class */ }
|
||||
// When inlining `f` into `g`, we need to erase class reification markers from `f` and the default lambda
|
||||
// (they will be recreated by `handleAnonymousObjectRegeneration` above if `T` is instantiated with another
|
||||
// reified type parameter), but not from the lambda passed to `f` in `g` (as reified type parameters inside
|
||||
// it do not belong to `f`, thus we cannot substitute them yet).
|
||||
if (inliningContext.isInliningLambda && inliningContext.lambdaInfo !is DefaultLambda) {
|
||||
// If objects are reified, the marker will be recreated by `handleAnonymousObjectRegeneration` above.
|
||||
if (!inliningContext.shouldReifyTypeParametersInObjects) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
||||
}
|
||||
} else {
|
||||
|
||||
+6
@@ -3822,6 +3822,12 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
inline fun <reified T> f(x: () -> String) = x()
|
||||
|
||||
inline fun <reified T> g() = f<Unit> {
|
||||
val x = { T::class.simpleName }
|
||||
x()!!
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
class OK
|
||||
|
||||
fun box() = g<OK>()
|
||||
+6
@@ -3822,6 +3822,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
+6
@@ -3822,6 +3822,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
+6
@@ -3822,6 +3822,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
+6
@@ -3822,6 +3822,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
+6
@@ -3822,6 +3822,12 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
+6
@@ -3822,6 +3822,12 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
|
||||
+5
@@ -3085,6 +3085,11 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");
|
||||
|
||||
Generated
+5
@@ -3085,6 +3085,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");
|
||||
|
||||
Generated
+5
@@ -3085,6 +3085,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonCapturingObjectInLambda.kt")
|
||||
public void testNonCapturingObjectInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");
|
||||
|
||||
Reference in New Issue
Block a user