diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt new file mode 100644 index 00000000000..4166e0598d9 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt @@ -0,0 +1,29 @@ +import kotlin.contracts.* + +fun foo(x: Any, y: Any) { + contract { + returns() implies (x is Int && y is String) + } + if (x !is Int || y !is String) { + throw IllegalStateException() + } +} + +fun test_1(x: Any, y: Any) { + foo(x = x, y = y) + x.inc() + y.length +} + +fun test_2(x: Any, y: Any) { + foo(x, y = y) + x.inc() + y.length +} + +fun test_3(x: Any, y: Any) { + foo(y = y, x = x) + x.inc() + y.length +} + diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.txt new file mode 100644 index 00000000000..e5acdd0b7e9 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.txt @@ -0,0 +1,30 @@ +FILE: namedArguments.kt + public final fun foo(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| + [R|Contract description] + < + Returns(WILDCARD) -> x is kotlin/Int && y is kotlin/String + > + { + [StubStatement] + when () { + (R|/x| !is R|kotlin/Int|) || (R|/y| !is R|kotlin/String|) -> { + throw R|java/lang/IllegalStateException.IllegalStateException|() + } + } + + } + public final fun test_1(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/foo|(x = R|/x|, y = R|/y|) + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/String.length| + } + public final fun test_2(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/foo|(R|/x|, y = R|/y|) + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/String.length| + } + public final fun test_3(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/foo|(y = R|/y|, x = R|/x|) + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/String.length| + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java index 74468a80a0e..ec7546bac28 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java @@ -593,6 +593,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt"); } + @TestMetadata("namedArguments.kt") + public void testNamedArguments() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt"); + } + @TestMetadata("propertyAccessors.kt") public void testPropertyAccessors() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/contracts/ConeConditionalEffectToFirVisitor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/contracts/ConeConditionalEffectToFirVisitor.kt index a7f9e28cbe7..4d6e2b5468c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/contracts/ConeConditionalEffectToFirVisitor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/contracts/ConeConditionalEffectToFirVisitor.kt @@ -92,12 +92,10 @@ fun createArgumentsMapping(qualifiedAccess: FirQualifiedAccess): Map { val function = qualifiedAccess.toResolvedCallableSymbol()?.fir as? FirSimpleFunction ?: return null - val nameToIndex = function.valueParameters.mapIndexed { index, parameter -> parameter.name to index }.toMap() - qualifiedAccess.arguments.forEachIndexed { index, argument -> - when (argument) { - is FirNamedArgumentExpression -> argumentsMapping[nameToIndex[argument.name]!!] = argument - else -> argumentsMapping[index] = argument - } + val parameterToIndex = function.valueParameters.mapIndexed { index, parameter -> parameter to index }.toMap() + val callArgumentMapping = qualifiedAccess.argumentMapping ?: return null + for (argument in qualifiedAccess.arguments) { + argumentsMapping[parameterToIndex.getValue(callArgumentMapping.getValue(argument))] = argument.unwrap() } } is FirVariableAssignment -> { @@ -105,4 +103,6 @@ fun createArgumentsMapping(qualifiedAccess: FirQualifiedAccess): Map