Generate debug metadata for lambdas which capture crossinline lambdas

After cold stream related fixes, we do not generate state machine until
the very last transformation of the lambda. Thus, it is safe to
generate debug metadata for that lambda.
 #KT-30694 Fixed
This commit is contained in:
Ilmir Usmanov
2019-03-28 22:16:01 +03:00
parent f09457c569
commit 3bfee39995
3 changed files with 15 additions and 6 deletions
@@ -66,9 +66,7 @@ class CoroutineTransformerMethodVisitor(
// It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls // It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls
private val needDispatchReceiver: Boolean = false, private val needDispatchReceiver: Boolean = false,
// May differ from containingClassInternalName in case of DefaultImpls // May differ from containingClassInternalName in case of DefaultImpls
private val internalNameForDispatchReceiver: String? = null, private val internalNameForDispatchReceiver: String? = null
// For crossinline lambdas we do not generate DebugMetadata annotation, otherwise it will be generated twice
private val isCrossinlineLambda: Boolean = false
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) { ) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState) private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
@@ -193,7 +191,7 @@ class CoroutineTransformerMethodVisitor(
fixLvtForParameters(methodNode, startLabel, endLabel) fixLvtForParameters(methodNode, startLabel, endLabel)
if (languageVersionSettings.isReleaseCoroutines() && !isCrossinlineLambda) { if (languageVersionSettings.isReleaseCoroutines()) {
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping) writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
} }
} }
@@ -109,8 +109,7 @@ class CoroutineTransformer(
languageVersionSettings = state.languageVersionSettings, languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName, containingClassInternalName = classBuilder.thisName,
isForNamedFunction = false, isForNamedFunction = false
isCrossinlineLambda = inliningContext.isContinuation
) )
} }
} }
@@ -23,6 +23,10 @@ inline suspend fun <T : Any> Flow<T>.collect(crossinline action: suspend (T) ->
override suspend fun emit(value: T) = action(value) override suspend fun emit(value: T) = action(value)
}) })
inline suspend fun inlineMe(crossinline block: suspend () -> Unit) = suspend {
block()
}
// FILE: Test.kt // FILE: Test.kt
import flow.* import flow.*
@@ -45,5 +49,13 @@ fun box(): String {
} }
} }
if ("(Test.kt:" !in str) return str if ("(Test.kt:" !in str) return str
builder {
inlineMe {
var continuation: Continuation<Unit>? = null
suspendCoroutineUninterceptedOrReturn<Unit> { continuation = it; Unit }
str = "$continuation"
}()
}
if ("(Test.kt:" !in str) return str
return "OK" return "OK"
} }