JVM: fix remapping of new T inside regenerated copies of T
In general, `InliningContext.findAnonymousTransformationInfo` was not reliable because it mapped each type to *some* info for that type, preferring ones with `shouldRegenerate == true` if those exist. Thus, it returned incorrect results if one type was regenerated multiple times, e.g. in a nested inlining context or because of a `finally` (which duplicates anonymous objects). The solution is to avoid a global map and attach the current transformation info directly to the current inlining context.
This commit is contained in:
@@ -27,7 +27,8 @@ class RegeneratedClassContext(
|
|||||||
nameGenerator: NameGenerator,
|
nameGenerator: NameGenerator,
|
||||||
typeRemapper: TypeRemapper,
|
typeRemapper: TypeRemapper,
|
||||||
lambdaInfo: LambdaInfo?,
|
lambdaInfo: LambdaInfo?,
|
||||||
override val callSiteInfo: InlineCallSiteInfo
|
override val callSiteInfo: InlineCallSiteInfo,
|
||||||
|
override val transformationInfo: TransformationInfo
|
||||||
) : InliningContext(
|
) : InliningContext(
|
||||||
parent, expressionMap, state, nameGenerator, typeRemapper, lambdaInfo, true
|
parent, expressionMap, state, nameGenerator, typeRemapper, lambdaInfo, true
|
||||||
) {
|
) {
|
||||||
@@ -48,7 +49,8 @@ open class InliningContext(
|
|||||||
|
|
||||||
var generateAssertField = false
|
var generateAssertField = false
|
||||||
|
|
||||||
private val internalNameToAnonymousObjectTransformationInfo = hashMapOf<String, AnonymousObjectTransformationInfo>()
|
open val transformationInfo: TransformationInfo?
|
||||||
|
get() = null
|
||||||
|
|
||||||
var isContinuation: Boolean = false
|
var isContinuation: Boolean = false
|
||||||
|
|
||||||
@@ -57,12 +59,13 @@ open class InliningContext(
|
|||||||
val root: RootInliningContext
|
val root: RootInliningContext
|
||||||
get() = if (isRoot) this as RootInliningContext else parent!!.root
|
get() = if (isRoot) this as RootInliningContext else parent!!.root
|
||||||
|
|
||||||
fun findAnonymousObjectTransformationInfo(internalName: String, searchInParent: Boolean = true): AnonymousObjectTransformationInfo? =
|
private val regeneratedAnonymousObjects = hashSetOf<String>()
|
||||||
internalNameToAnonymousObjectTransformationInfo[internalName]
|
|
||||||
?: if (searchInParent) parent?.findAnonymousObjectTransformationInfo(internalName, searchInParent) else null
|
|
||||||
|
|
||||||
fun recordIfNotPresent(internalName: String, info: AnonymousObjectTransformationInfo) {
|
fun isRegeneratedAnonymousObject(internalName: String): Boolean =
|
||||||
internalNameToAnonymousObjectTransformationInfo.putIfAbsent(internalName, info)
|
internalName in regeneratedAnonymousObjects || (parent != null && parent.isRegeneratedAnonymousObject(internalName))
|
||||||
|
|
||||||
|
fun recordRegeneratedAnonymousObject(internalName: String) {
|
||||||
|
regeneratedAnonymousObjects.add(internalName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun subInlineLambda(lambdaInfo: LambdaInfo): InliningContext =
|
fun subInlineLambda(lambdaInfo: LambdaInfo): InliningContext =
|
||||||
@@ -82,10 +85,11 @@ open class InliningContext(
|
|||||||
fun subInlineWithClassRegeneration(
|
fun subInlineWithClassRegeneration(
|
||||||
generator: NameGenerator,
|
generator: NameGenerator,
|
||||||
newTypeMappings: MutableMap<String, String?>,
|
newTypeMappings: MutableMap<String, String?>,
|
||||||
callSiteInfo: InlineCallSiteInfo
|
callSiteInfo: InlineCallSiteInfo,
|
||||||
|
transformationInfo: TransformationInfo
|
||||||
): InliningContext = RegeneratedClassContext(
|
): InliningContext = RegeneratedClassContext(
|
||||||
this, expressionMap, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings),
|
this, expressionMap, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings),
|
||||||
lambdaInfo, callSiteInfo
|
lambdaInfo, callSiteInfo, transformationInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ class MethodInliner(
|
|||||||
if (!inliningContext.isInliningLambda) {
|
if (!inliningContext.isInliningLambda) {
|
||||||
inliningContext.root.state.globalInlineContext.recordTypeFromInlineFunction(info.oldClassName)
|
inliningContext.root.state.globalInlineContext.recordTypeFromInlineFunction(info.oldClassName)
|
||||||
}
|
}
|
||||||
|
if (info.shouldRegenerate(isSameModule)) {
|
||||||
|
inliningContext.recordRegeneratedAnonymousObject(info.oldClassName)
|
||||||
|
}
|
||||||
transformations.add(info)
|
transformations.add(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +174,8 @@ class MethodInliner(
|
|||||||
val childInliningContext = inliningContext.subInlineWithClassRegeneration(
|
val childInliningContext = inliningContext.subInlineWithClassRegeneration(
|
||||||
inliningContext.nameGenerator,
|
inliningContext.nameGenerator,
|
||||||
currentTypeMapping,
|
currentTypeMapping,
|
||||||
inlineCallSiteInfo
|
inlineCallSiteInfo,
|
||||||
|
transformationInfo!!
|
||||||
)
|
)
|
||||||
val transformer = transformationInfo!!.createTransformer(
|
val transformer = transformationInfo!!.createTransformer(
|
||||||
childInliningContext, isSameModule, fakeContinuationName
|
childInliningContext, isSameModule, fakeContinuationName
|
||||||
@@ -305,51 +309,33 @@ class MethodInliner(
|
|||||||
inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter)
|
inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter)
|
||||||
} else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
|
} else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
|
||||||
//TODO add proper message
|
//TODO add proper message
|
||||||
assert(transformationInfo is AnonymousObjectTransformationInfo) {
|
var info = transformationInfo as? AnonymousObjectTransformationInfo ?: throw AssertionError(
|
||||||
"<init> call doesn't correspond to object transformation info for '$owner.$name': $transformationInfo"
|
"<init> call doesn't correspond to object transformation info for '$owner.$name': $transformationInfo"
|
||||||
|
)
|
||||||
|
val objectConstructsItself = inlineCallSiteInfo.ownerClassName == info.oldClassName
|
||||||
|
if (objectConstructsItself) {
|
||||||
|
// inline fun f() -> new f$1 -> fun something() in class f$1 -> new f$1
|
||||||
|
// ^-- fetch the info that was created for this instruction
|
||||||
|
info = inliningContext.parent?.transformationInfo as? AnonymousObjectTransformationInfo
|
||||||
|
?: throw AssertionError("anonymous object $owner constructs itself, but we have no info on in")
|
||||||
}
|
}
|
||||||
val parent = inliningContext.parent
|
if (info.shouldRegenerate(isSameModule)) {
|
||||||
val shouldRegenerate = transformationInfo!!.shouldRegenerate(isSameModule)
|
|
||||||
val isContinuation = parent != null && parent.isContinuation
|
|
||||||
if (shouldRegenerate || isContinuation) {
|
|
||||||
assert(shouldRegenerate || inlineCallSiteInfo.ownerClassName == transformationInfo!!.oldClassName) { "Only coroutines can call their own constructors" }
|
|
||||||
|
|
||||||
//put additional captured parameters on stack
|
|
||||||
var info = transformationInfo as AnonymousObjectTransformationInfo
|
|
||||||
|
|
||||||
val oldInfo = inliningContext.findAnonymousObjectTransformationInfo(owner)
|
|
||||||
if (oldInfo != null && isContinuation) {
|
|
||||||
info = oldInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
val isContinuationCreate = isContinuation && oldInfo != null && resultNode.name == "create" &&
|
|
||||||
resultNode.desc.endsWith(")" + languageVersionSettings.continuationAsmType().descriptor)
|
|
||||||
|
|
||||||
for (capturedParamDesc in info.allRecapturedParameters) {
|
for (capturedParamDesc in info.allRecapturedParameters) {
|
||||||
if (capturedParamDesc.fieldName == AsmUtil.THIS && isContinuationCreate) {
|
val realDesc = if (objectConstructsItself && capturedParamDesc.fieldName == AsmUtil.THIS) {
|
||||||
// Common inliner logic doesn't support cases when transforming anonymous object can
|
// The captures in `info` are relative to the parent context, so a normal `this` there
|
||||||
// be instantiated by itself.
|
// is a captured outer `this` here.
|
||||||
// To support such cases workaround with 'oldInfo' is used.
|
CapturedParamDesc(Type.getObjectType(owner), AsmUtil.CAPTURED_THIS_FIELD, capturedParamDesc.type)
|
||||||
// But it corresponds to outer context and a bit inapplicable for nested 'create' method context.
|
} else capturedParamDesc
|
||||||
// 'This' in outer context corresponds to outer instance in current
|
visitFieldInsn(
|
||||||
visitFieldInsn(
|
Opcodes.GETSTATIC, realDesc.containingLambdaName,
|
||||||
Opcodes.GETSTATIC, owner,
|
FieldRemapper.foldName(realDesc.fieldName), realDesc.type.descriptor
|
||||||
FieldRemapper.foldName(AsmUtil.CAPTURED_THIS_FIELD), capturedParamDesc.type.descriptor
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
visitFieldInsn(
|
|
||||||
Opcodes.GETSTATIC, capturedParamDesc.containingLambdaName,
|
|
||||||
FieldRemapper.foldName(capturedParamDesc.fieldName), capturedParamDesc.type.descriptor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
super.visitMethodInsn(opcode, info.newClassName, name, info.newConstructorDescriptor, itf)
|
super.visitMethodInsn(opcode, info.newClassName, name, info.newConstructorDescriptor, itf)
|
||||||
|
|
||||||
//TODO: add new inner class also for other contexts
|
//TODO: add new inner class also for other contexts
|
||||||
if (inliningContext.parent is RegeneratedClassContext) {
|
if (inliningContext.parent is RegeneratedClassContext) {
|
||||||
inliningContext.parent.typeRemapper.addAdditionalMappings(
|
inliningContext.parent.typeRemapper.addAdditionalMappings(info.oldClassName, info.newClassName)
|
||||||
transformationInfo!!.oldClassName, transformationInfo!!.newClassName
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transformationInfo = null
|
transformationInfo = null
|
||||||
@@ -826,8 +812,7 @@ class MethodInliner(
|
|||||||
|
|
||||||
private fun isAnonymousClassThatMustBeRegenerated(type: Type?): Boolean {
|
private fun isAnonymousClassThatMustBeRegenerated(type: Type?): Boolean {
|
||||||
if (type == null || type.sort != Type.OBJECT) return false
|
if (type == null || type.sort != Type.OBJECT) return false
|
||||||
val info = inliningContext.findAnonymousObjectTransformationInfo(type.internalName)
|
return inliningContext.isRegeneratedAnonymousObject(type.internalName)
|
||||||
return info != null && info.shouldRegenerate(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildConstructorInvocation(
|
private fun buildConstructorInvocation(
|
||||||
@@ -849,7 +834,7 @@ class MethodInliner(
|
|||||||
// inline lambda cannot possibly reference it, while V is not yet bound so regenerating the object while inlining
|
// inline lambda cannot possibly reference it, while V is not yet bound so regenerating the object while inlining
|
||||||
// the lambda into f() is pointless.
|
// the lambda into f() is pointless.
|
||||||
val inNonDefaultLambda = inliningContext.isInliningLambda && inliningContext.lambdaInfo !is DefaultLambda
|
val inNonDefaultLambda = inliningContext.isInliningLambda && inliningContext.lambdaInfo !is DefaultLambda
|
||||||
val info = AnonymousObjectTransformationInfo(
|
return AnonymousObjectTransformationInfo(
|
||||||
anonymousType, needReification && !inNonDefaultLambda, lambdaMapping,
|
anonymousType, needReification && !inNonDefaultLambda, lambdaMapping,
|
||||||
inliningContext.classRegeneration,
|
inliningContext.classRegeneration,
|
||||||
isAlreadyRegenerated(anonymousType),
|
isAlreadyRegenerated(anonymousType),
|
||||||
@@ -858,19 +843,6 @@ class MethodInliner(
|
|||||||
inliningContext.nameGenerator,
|
inliningContext.nameGenerator,
|
||||||
capturesAnonymousObjectThatMustBeRegenerated
|
capturesAnonymousObjectThatMustBeRegenerated
|
||||||
)
|
)
|
||||||
|
|
||||||
val memoizeAnonymousObject = inliningContext.findAnonymousObjectTransformationInfo(anonymousType)
|
|
||||||
if (memoizeAnonymousObject == null ||
|
|
||||||
//anonymous object could be inlined in several context without transformation (keeps same class name)
|
|
||||||
// and on further inlining such code some of such cases would be transformed and some not,
|
|
||||||
// so we should distinguish one classes from another more clearly
|
|
||||||
!memoizeAnonymousObject.shouldRegenerate(isSameModule) &&
|
|
||||||
info.shouldRegenerate(isSameModule)
|
|
||||||
) {
|
|
||||||
|
|
||||||
inliningContext.recordIfNotPresent(anonymousType, info)
|
|
||||||
}
|
|
||||||
return info
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isAlreadyRegenerated(owner: String): Boolean {
|
private fun isAlreadyRegenerated(owner: String): Boolean {
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
// NO_CHECK_LAMBDA_INLINING
|
||||||
|
// FILE: 1.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun foo(crossinline x: () -> Unit) = suspend {
|
||||||
|
try { } finally {
|
||||||
|
// This object is regenerated twice (normal return & "catch Throwable, execute finally, and rethrow")
|
||||||
|
// It doesn't *need* to be, but this should work regardless.
|
||||||
|
{ x() }()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import helpers.*
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
var result = "fail"
|
||||||
|
fun box(): String {
|
||||||
|
suspend {
|
||||||
|
foo { result = "OK" }()
|
||||||
|
}.startCoroutine(EmptyContinuation)
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
// NO_CHECK_LAMBDA_INLINING
|
||||||
|
// FILE: 1.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun foo(crossinline x: () -> Unit) = suspend {
|
||||||
|
try { } finally {
|
||||||
|
// This object is regenerated twice (normal return & "catch Throwable, execute finally, and rethrow")
|
||||||
|
// It doesn't *need* to be, but this should work regardless.
|
||||||
|
suspend { x() }()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import helpers.*
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
var result = "fail"
|
||||||
|
fun box(): String {
|
||||||
|
suspend {
|
||||||
|
foo { result = "OK" }()
|
||||||
|
}.startCoroutine(EmptyContinuation)
|
||||||
|
return result
|
||||||
|
}
|
||||||
+10
@@ -3953,6 +3953,16 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedAnonymousObject.kt")
|
||||||
|
public void testTwiceRegeneratedAnonymousObject() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedAnonymousObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedSuspendLambda.kt")
|
||||||
|
public void testTwiceRegeneratedSuspendLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedSuspendLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+10
@@ -3953,6 +3953,16 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedAnonymousObject.kt")
|
||||||
|
public void testTwiceRegeneratedAnonymousObject() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedAnonymousObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedSuspendLambda.kt")
|
||||||
|
public void testTwiceRegeneratedSuspendLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedSuspendLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+10
@@ -3848,6 +3848,16 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedAnonymousObject.kt")
|
||||||
|
public void testTwiceRegeneratedAnonymousObject() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedAnonymousObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedSuspendLambda.kt")
|
||||||
|
public void testTwiceRegeneratedSuspendLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedSuspendLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+10
@@ -3848,6 +3848,16 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedAnonymousObject.kt")
|
||||||
|
public void testTwiceRegeneratedAnonymousObject() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedAnonymousObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedSuspendLambda.kt")
|
||||||
|
public void testTwiceRegeneratedSuspendLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedSuspendLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+10
@@ -3418,6 +3418,16 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedAnonymousObject.kt")
|
||||||
|
public void testTwiceRegeneratedAnonymousObject() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedAnonymousObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedSuspendLambda.kt")
|
||||||
|
public void testTwiceRegeneratedSuspendLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedSuspendLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+10
@@ -3418,6 +3418,16 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedAnonymousObject.kt")
|
||||||
|
public void testTwiceRegeneratedAnonymousObject() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedAnonymousObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("twiceRegeneratedSuspendLambda.kt")
|
||||||
|
public void testTwiceRegeneratedSuspendLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/suspend/twiceRegeneratedSuspendLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
@TestMetadata("compiler/testData/codegen/boxInline/suspend/callableReference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user