K2: handle suspend anonymous functions properly in various compiler parts

#KT-58332 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-05-05 11:56:37 +02:00
committed by Space Team
parent aec0def5ca
commit 0906258d03
24 changed files with 95 additions and 19 deletions
@@ -32222,6 +32222,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendAndFunConversionInDisabledMode.kt");
}
@Test
@TestMetadata("suspendCallFromAnonymousSuspend.kt")
public void testSuspendCallFromAnonymousSuspend() throws Exception {
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendCallFromAnonymousSuspend.kt");
}
@Test
@TestMetadata("suspendConversionCompatibility.kt")
public void testSuspendConversionCompatibility() throws Exception {
@@ -32222,6 +32222,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendAndFunConversionInDisabledMode.kt");
}
@Test
@TestMetadata("suspendCallFromAnonymousSuspend.kt")
public void testSuspendCallFromAnonymousSuspend() throws Exception {
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendCallFromAnonymousSuspend.kt");
}
@Test
@TestMetadata("suspendConversionCompatibility.kt")
public void testSuspendConversionCompatibility() throws Exception {
@@ -32222,6 +32222,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendAndFunConversionInDisabledMode.kt");
}
@Test
@TestMetadata("suspendCallFromAnonymousSuspend.kt")
public void testSuspendCallFromAnonymousSuspend() throws Exception {
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendCallFromAnonymousSuspend.kt");
}
@Test
@TestMetadata("suspendConversionCompatibility.kt")
public void testSuspendConversionCompatibility() throws Exception {
@@ -32318,6 +32318,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendAndFunConversionInDisabledMode.kt");
}
@Test
@TestMetadata("suspendCallFromAnonymousSuspend.kt")
public void testSuspendCallFromAnonymousSuspend() throws Exception {
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendCallFromAnonymousSuspend.kt");
}
@Test
@TestMetadata("suspendConversionCompatibility.kt")
public void testSuspendConversionCompatibility() throws Exception {
@@ -130,9 +130,12 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
private fun findEnclosingSuspendFunction(context: CheckerContext): FirFunction? {
return context.containingDeclarations.lastOrNull {
when (it) {
is FirAnonymousFunction -> it.typeRef.coneType.isSuspendOrKSuspendFunctionType(context.session)
is FirSimpleFunction -> it.isSuspend
else -> false
is FirAnonymousFunction ->
if (it.isLambda) it.typeRef.coneType.isSuspendOrKSuspendFunctionType(context.session) else it.isSuspend
is FirSimpleFunction ->
it.isSuspend
else ->
false
}
} as? FirFunction
}
@@ -505,7 +505,7 @@ class FirElementSerializer private constructor(
simpleFunction?.isInline == true,
simpleFunction?.isTailRec == true,
simpleFunction?.isExternal == true,
simpleFunction?.isSuspend == true,
function.isSuspend,
simpleFunction?.isExpect == true,
shouldSetStableParameterNames(function),
)
@@ -227,6 +227,7 @@ private fun FirFunction.copyToFreeAnonymousFunction(approximator: AbstractTypeAp
}
})
typeParameters += typeParameterSet
status = function.status
}
}
@@ -564,7 +564,7 @@ class Fir2IrDeclarationStorage(
val visibility = simpleFunction?.visibility ?: Visibilities.Local
val isSuspend =
if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendOrKSuspendFunctionType(session) == true
else simpleFunction?.isSuspend == true
else function.isSuspend
val created = function.convertWithOffsets { startOffset, endOffset ->
val result = declareIrSimpleFunction(signature) { symbol ->
classifierStorage.preCacheTypeParameters(function, symbol)
@@ -1660,6 +1660,9 @@ class DeclarationsConverter(
label = context.getLastLabel(functionDeclaration)
val labelName = label?.name ?: context.calleeNamesForLambda.lastOrNull()?.identifier
target = FirFunctionTarget(labelName = labelName, isLambda = false)
if (modifiers.hasSuspend()) {
status = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_SUSPEND_FUNCTION_EXPRESSION
}
}
} else {
val functionName = identifier.nameAsSafeName()
@@ -1441,6 +1441,9 @@ open class RawFirBuilder(
hasExplicitParameterList = true
label = context.getLastLabel(function)
labelName = label?.name ?: context.calleeNamesForLambda.lastOrNull()?.identifier
if (function.hasModifier(SUSPEND_KEYWORD)) {
status = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_SUSPEND_FUNCTION_EXPRESSION
}
}
} else {
FirSimpleFunctionBuilder().apply {
@@ -59,6 +59,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
override lateinit var moduleData: FirModuleData
override lateinit var origin: FirDeclarationOrigin
override var attributes: FirDeclarationAttributes = FirDeclarationAttributes()
override var status: FirDeclarationStatus = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
override lateinit var returnTypeRef: FirTypeRef
var receiverParameter: FirReceiverParameter? = null
override var deprecationsProvider: DeprecationsProvider = UnresolvedDeprecationProvider
@@ -86,6 +87,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
moduleData,
origin,
attributes,
status,
returnTypeRef,
receiverParameter,
deprecationsProvider,
@@ -107,13 +109,6 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
)
}
@Deprecated("Modification of 'status' has no impact for FirAnonymousFunctionBuilder", level = DeprecationLevel.HIDDEN)
override var status: FirDeclarationStatus
get() = throw IllegalStateException()
set(_) {
throw IllegalStateException()
}
}
@OptIn(ExperimentalContracts::class)
@@ -136,6 +131,7 @@ inline fun buildAnonymousFunctionCopy(original: FirAnonymousFunction, init: FirA
copyBuilder.moduleData = original.moduleData
copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes.copy()
copyBuilder.status = original.status
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverParameter = original.receiverParameter
copyBuilder.deprecationsProvider = original.deprecationsProvider
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.InlineStatus
import org.jetbrains.kotlin.fir.declarations.asResolveState
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
@@ -50,6 +49,7 @@ internal class FirAnonymousFunctionImpl(
override val moduleData: FirModuleData,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
override var status: FirDeclarationStatus,
override var returnTypeRef: FirTypeRef,
override var receiverParameter: FirReceiverParameter?,
override var deprecationsProvider: DeprecationsProvider,
@@ -69,8 +69,6 @@ internal class FirAnonymousFunctionImpl(
override val typeParameters: MutableList<FirTypeParameter>,
override var typeRef: FirTypeRef,
) : FirAnonymousFunction() {
override var status: FirDeclarationStatus = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
init {
symbol.bind(this)
@OptIn(ResolveStateAccess::class)
@@ -23,6 +23,11 @@ class FirResolvedDeclarationStatusImpl(
Modality.FINAL,
EffectiveVisibility.Public
)
val DEFAULT_STATUS_FOR_SUSPEND_FUNCTION_EXPRESSION = FirResolvedDeclarationStatusImpl(
Visibilities.Local,
Modality.FINAL,
EffectiveVisibility.Public
).apply { isSuspend = true }
}
internal constructor(
@@ -96,4 +96,10 @@ class FirAllModifierRenderer : FirModifierRenderer() {
renderModifier("external")
}
}
override fun renderModifiers(anonymousFunction: FirAnonymousFunction) {
if (anonymousFunction.isSuspend) {
renderModifier("suspend")
}
}
}
@@ -22,6 +22,7 @@ abstract class FirModifierRenderer {
abstract fun renderModifiers(backingField: FirBackingField)
abstract fun renderModifiers(constructor: FirConstructor)
abstract fun renderModifiers(propertyAccessor: FirPropertyAccessor)
abstract fun renderModifiers(anonymousFunction: FirAnonymousFunction)
open fun renderModifiers(valueParameter: FirValueParameter) {
if (valueParameter.isCrossinline) {
renderModifier("crossinline")
@@ -57,4 +57,10 @@ class FirPartialModifierRenderer : FirModifierRenderer() {
override fun renderModifiers(propertyAccessor: FirPropertyAccessor) {
}
override fun renderModifiers(anonymousFunction: FirAnonymousFunction) {
if (anonymousFunction.isSuspend) {
renderModifier("suspend")
}
}
}
@@ -388,6 +388,7 @@ class FirRenderer(
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
annotationRenderer?.render(anonymousFunction)
modifierRenderer?.renderModifiers(anonymousFunction)
declarationRenderer?.render(anonymousFunction)
print(" ")
val receiverParameter = anonymousFunction.receiverParameter
@@ -271,8 +271,9 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
defaultNull("invocationKind", "label", "body", "controlFlowGraphReference")
default("inlineStatus", "InlineStatus.Unknown")
default("contractDescription", "FirEmptyContractDescription")
default("status", "FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS")
withCopy()
useTypes(emptyContractDescriptionType)
useTypes(emptyContractDescriptionType, resolvedDeclarationStatusImport)
}
builder(propertyAccessor) {
@@ -565,7 +565,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(contractElementDeclaration)
val implementationsWithoutStatusAndTypeParameters = listOf(
"FirAnonymousFunctionImpl",
"FirValueParameterImpl",
"FirDefaultSetterValueParameter",
"FirErrorPropertyImpl",
@@ -582,7 +581,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
configureFieldInAllImplementations(
"typeParameters",
implementationPredicate = { it.type != "FirAnonymousFunctionImpl" && it.type in implementationsWithoutStatusAndTypeParameters }
implementationPredicate = { it.type in implementationsWithoutStatusAndTypeParameters }
) {
defaultEmptyList(it)
useTypes(resolvedDeclarationStatusImplType)
@@ -9,4 +9,5 @@ import org.jetbrains.kotlin.fir.tree.generator.model.ArbitraryImportable
val phaseAsResolveStateExtentionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "asResolveState")
val resolvePhaseExtensionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "resolvePhase")
val resolveStateAccessImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "ResolveStateAccess")
val resolveStateAccessImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "ResolveStateAccess")
val resolvedDeclarationStatusImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations.impl", "FirResolvedDeclarationStatusImpl")
@@ -0,0 +1,9 @@
FILE: suspendCallFromAnonymousSuspend.kt
public final fun foo(): R|kotlin/Unit| {
suspend fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
R|/bar|()
}
}
public final suspend fun bar(): R|kotlin/Unit| {
}
@@ -0,0 +1,12 @@
// FIR_IDENTICAL
// FIR_DUMP
fun foo() {
suspend fun() {
bar()
}
}
suspend fun bar() {
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ISSUE: KT-58332
fun foo() {
@@ -33090,6 +33090,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendAndFunConversionInDisabledMode.kt");
}
@Test
@TestMetadata("suspendCallFromAnonymousSuspend.kt")
public void testSuspendCallFromAnonymousSuspend() throws Exception {
runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendCallFromAnonymousSuspend.kt");
}
@Test
@TestMetadata("suspendConversionCompatibility.kt")
public void testSuspendConversionCompatibility() throws Exception {