diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index dcdb02fa4dd..7dc05b6419d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -446,9 +446,6 @@ internal fun FirReference.statementOrigin(): IrStatementOrigin? { } } -fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? = - declarations.filterIsInstance().firstOrNull()?.takeIf { it.isPrimary } - internal fun IrDeclarationParent.declareThisReceiverParameter( symbolTable: SymbolTable, thisType: IrType, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index e69108a83ff..392822622f5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.fir.backend.generators import org.jetbrains.kotlin.fir.backend.* -import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin -import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction -import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.psi @@ -19,6 +16,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.calls.isFunctional +import org.jetbrains.kotlin.fir.resolve.getCorrespondingConstructorReferenceOrNull import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol @@ -327,6 +325,7 @@ class CallAndReferenceGenerator( val calleeReference = when (call) { is FirFunctionCall -> call.calleeReference is FirDelegatedConstructorCall -> call.calleeReference + is FirAnnotationCall -> call.getCorrespondingConstructorReferenceOrNull(session) else -> null } as? FirResolvedNamedReference val function = (calleeReference?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir @@ -334,7 +333,7 @@ class CallAndReferenceGenerator( val argumentMapping = call.argumentMapping if (argumentMapping != null && argumentMapping.isNotEmpty()) { if (valueParameters != null) { - return applyArgumentsWithReorderingIfNeeded(argumentMapping, valueParameters) + return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters) } } for ((index, argument) in call.arguments.withIndex()) { @@ -365,10 +364,15 @@ class CallAndReferenceGenerator( } private fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReorderingIfNeeded( + call: FirCall, argumentMapping: Map, valueParameters: List, ): IrExpressionBase { - if (needArgumentReordering(argumentMapping.values, valueParameters)) { + // Assuming compile-time constants only inside annotation, we don't need a block to reorder arguments to preserve semantics. + // But, we still need to pick correct indices for named arguments. + if (call !is FirAnnotationCall && + needArgumentReordering(argumentMapping.values, valueParameters) + ) { return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply { for ((argument, parameter) in argumentMapping) { val parameterIndex = valueParameters.indexOf(parameter) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 39b91499f06..77d5c2e1ffe 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.references.FirThisReference +import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError @@ -462,3 +463,16 @@ private fun FirQualifiedAccess.expressionTypeOrUnitForAssignment(): ConeKotlinTy } return StandardClassIds.Unit.constructClassLikeType(emptyArray(), isNullable = false) } + +fun FirAnnotationCall.getCorrespondingConstructorReferenceOrNull(session: FirSession): FirResolvedNamedReference? = + annotationTypeRef.coneTypeSafe()?.classId?.let { + (session.firSymbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol)?.fir + ?.getPrimaryConstructorIfAny() + ?.let { annotationConstructor -> + buildResolvedNamedReference { + source = this@getCorrespondingConstructorReferenceOrNull.source + name = it.shortClassName + resolvedSymbol = annotationConstructor.symbol + } + } + } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt index 316a260271b..1a281f073d9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirArgumentsToParametersMapper.kt @@ -25,7 +25,20 @@ data class ArgumentMapping( // parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ] val parameterToCallArgumentMap: Map, val diagnostics: List -) +) { + fun toArgumentToParameterMapping(): Map { + val argumentToParameterMapping = mutableMapOf() + parameterToCallArgumentMap.forEach { (valueParameter, resolvedArgument) -> + when (resolvedArgument) { + is ResolvedCallArgument.SimpleArgument -> argumentToParameterMapping[resolvedArgument.callArgument] = valueParameter + is ResolvedCallArgument.VarargArgument -> resolvedArgument.arguments.forEach { + argumentToParameterMapping[it] = valueParameter + } + } + } + return argumentToParameterMapping + } +} private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList()) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index cc731ad131c..1728b2fc043 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -159,16 +159,7 @@ internal object MapArguments : ResolutionStage() { val function = symbol.fir val mapping = mapArguments(callInfo.arguments, function) - val argumentToParameterMapping = mutableMapOf() - mapping.parameterToCallArgumentMap.forEach { (valueParameter, resolvedArgument) -> - when (resolvedArgument) { - is ResolvedCallArgument.SimpleArgument -> argumentToParameterMapping[resolvedArgument.callArgument] = valueParameter - is ResolvedCallArgument.VarargArgument -> resolvedArgument.arguments.forEach { - argumentToParameterMapping[it] = valueParameter - } - } - } - candidate.argumentMapping = argumentToParameterMapping + candidate.argumentMapping = mapping.toArgumentToParameterMapping() var applicability = CandidateApplicability.RESOLVED mapping.diagnostics.forEach { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 232d1187291..47ef5f6bb7d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.candidate +import org.jetbrains.kotlin.fir.resolve.calls.mapArguments import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver @@ -641,6 +642,14 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform (annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also { // TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls it.argumentList.transformArguments(integerLiteralTypeApproximator, null) + if (it.arguments.any { arg -> arg is FirNamedArgumentExpression }) { + annotationCall.getCorrespondingConstructorReferenceOrNull(session)?.let { calleeReference -> + val argumentMapping = + mapArguments(it.arguments, calleeReference.resolvedSymbol.fir as FirFunction<*>) + .toArgumentToParameterMapping() + it.replaceArgumentList(buildResolvedArgumentList(argumentMapping)) + } + } it.replaceResolveStatus(status) dataFlowAnalyzer.exitAnnotationCall(it) }.compose() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt index 9ff689c003a..33dd4ff9d3d 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt @@ -93,6 +93,9 @@ val FirClassSymbol<*>.superConeTypes val FirClass<*>.superConeTypes get() = superTypeRefs.mapNotNull { it.coneTypeSafe() } +fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? = + declarations.filterIsInstance().firstOrNull()?.takeIf { it.isPrimary } + fun FirRegularClass.collectEnumEntries(): Collection { assert(classKind == ClassKind.ENUM_CLASS) return declarations.filterIsInstance() diff --git a/compiler/testData/ir/irText/declarations/annotations/annotationsWithDefaultParameterValues.fir.txt b/compiler/testData/ir/irText/declarations/annotations/annotationsWithDefaultParameterValues.fir.txt index 599caaace8f..1fac627a538 100644 --- a/compiler/testData/ir/irText/declarations/annotations/annotationsWithDefaultParameterValues.fir.txt +++ b/compiler/testData/ir/irText/declarations/annotations/annotationsWithDefaultParameterValues.fir.txt @@ -57,7 +57,7 @@ FILE fqName: fileName:/annotationsWithDefaultParameterValues.kt BLOCK_BODY FUN name:test4 visibility:public modality:FINAL <> () returnType:kotlin.Unit annotations: - A(x = '456', y = ) + A(x = , y = '456') BLOCK_BODY FUN name:test5 visibility:public modality:FINAL <> () returnType:kotlin.Unit annotations: diff --git a/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt b/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt index 55c5dbc6cc2..2208d3bcad9 100644 --- a/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt +++ b/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt @@ -63,7 +63,7 @@ FILE fqName: fileName:/castsInsideCoroutineInference.kt CALL 'public final fun TODO (): kotlin.Nothing [inline] declared in kotlin' type=kotlin.Nothing origin=null FUN name:onCompletion visibility:public modality:FINAL ($receiver:.Flow.onCompletion>, action:kotlin.coroutines.SuspendFunction1) returnType:IrErrorType annotations: - Deprecated(message = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:HIDDEN' type=kotlin.DeprecationLevel, replaceWith = 'binary compatibility with a version w/o FlowCollector receiver', level = ) + Deprecated(message = 'binary compatibility with a version w/o FlowCollector receiver', replaceWith = , level = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:HIDDEN' type=kotlin.DeprecationLevel) TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] $receiver: VALUE_PARAMETER name: type:.Flow.onCompletion> VALUE_PARAMETER name:action index:0 type:kotlin.coroutines.SuspendFunction1