[FIR] Use argument mapping from resolved call for contract argument mapping
This commit is contained in:
+29
@@ -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
|
||||
}
|
||||
|
||||
+30
@@ -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|<local>/x| !is R|kotlin/Int|) || (R|<local>/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|<local>/x|, y = R|<local>/y|)
|
||||
R|<local>/x|.R|kotlin/Int.inc|()
|
||||
R|<local>/y|.R|kotlin/String.length|
|
||||
}
|
||||
public final fun test_2(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| {
|
||||
R|/foo|(R|<local>/x|, y = R|<local>/y|)
|
||||
R|<local>/x|.R|kotlin/Int.inc|()
|
||||
R|<local>/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|<local>/y|, x = R|<local>/x|)
|
||||
R|<local>/x|.R|kotlin/Int.inc|()
|
||||
R|<local>/y|.R|kotlin/String.length|
|
||||
}
|
||||
+5
@@ -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");
|
||||
|
||||
+7
-7
@@ -92,12 +92,10 @@ fun createArgumentsMapping(qualifiedAccess: FirQualifiedAccess): Map<Int, FirExp
|
||||
when (qualifiedAccess) {
|
||||
is FirFunctionCall -> {
|
||||
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<Int, FirExp
|
||||
}
|
||||
}
|
||||
return argumentsMapping
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirExpression.unwrap(): FirExpression = if (this is FirWrappedArgumentExpression) expression else this
|
||||
Reference in New Issue
Block a user