From 54e725668f4bf8c8b6ac7197529d15c44b50bf8b Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 18 Mar 2020 13:13:32 +0100 Subject: [PATCH] Ignore reified type parameters when regenerating objects from lambdas All reified type parameters referenced by objects in non-default lambdas are from outside the inline call, thus they cannot be substituted yet. This means if the only reason for object regeneration is reification, then regeneration isn't actually necessary. E.g. in this code: inline fun f(x: () -> Unit) = x() inline fun g() = f { { println(V::class.simpleName) }() } we first inline the lambda into f(), then inline f()-with-lambda into g(). Because the object inside the lambda captures nothing from outside g(), the original class can be used both times. This brings the JVM_IR backend into complete compliance with KT-28064. --- .../kotlin/codegen/inline/MethodInliner.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 127b6fe047b..5456bbdb1d2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -859,9 +859,20 @@ class MethodInliner( needReification: Boolean, capturesAnonymousObjectThatMustBeRegenerated: Boolean ): AnonymousObjectTransformationInfo { - + // In objects inside non-default lambdas, all reified type parameters are free (not from the function + // we're inlining into) so there's nothing to reify: + // + // inline fun f(x: () -> KClass = { { T::class }() }) = x() + // fun a() = f() + // fun b() = f { { Int::class }() } // non-default lambda + // inline fun c() = f { { V::class }() } + // + // -- in a(), the default lambda captures T so a regeneration is needed; but in b() and c(), the non-default + // lambda cannot possibly reference it, while V is not yet bound so regenerating the object while inlining + // the lambda into f() is pointless. + val inNonDefaultLambda = inliningContext.isInliningLambda && inliningContext.lambdaInfo !is DefaultLambda val info = AnonymousObjectTransformationInfo( - anonymousType, needReification, lambdaMapping, + anonymousType, needReification && !inNonDefaultLambda, lambdaMapping, inliningContext.classRegeneration, isAlreadyRegenerated(anonymousType), desc,