[FIR] Consider call site in argument mapping handling for set operator call

^KT-56542 Fixed
^KT-56714 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-02-20 17:26:48 +02:00
committed by Space Team
parent cbc8b74e89
commit df47581c5a
12 changed files with 135 additions and 6 deletions
@@ -921,6 +921,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/overloadWithDefault.kt");
}
@Test
@TestMetadata("setWithTrailingLambda.kt")
public void testSetWithTrailingLambda() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/setWithTrailingLambda.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
@@ -957,6 +963,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/vararg.kt");
}
@Test
@TestMetadata("varargFromJava.kt")
public void testVarargFromJava() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/varargFromJava.kt");
}
@Test
@TestMetadata("varargOfLambdasWithReceiver.kt")
public void testVarargOfLambdasWithReceiver() throws Exception {
@@ -784,6 +784,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/overloadWithDefault.kt");
}
@TestMetadata("setWithTrailingLambda.kt")
public void testSetWithTrailingLambda() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/setWithTrailingLambda.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/simple.kt");
@@ -814,6 +819,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/vararg.kt");
}
@TestMetadata("varargFromJava.kt")
public void testVarargFromJava() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/varargFromJava.kt");
}
@TestMetadata("varargOfLambdasWithReceiver.kt")
public void testVarargOfLambdasWithReceiver() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/varargOfLambdasWithReceiver.kt");
@@ -0,0 +1,38 @@
FILE: setWithTrailingLambda.kt
public final fun test(m: R|MyMap<EditorData, kotlin/Any>|): R|kotlin/Unit| {
R|<local>/m|.R|SubstitutionOverride</MyMap.set: R|kotlin/Unit|>|<R|(kotlin/String, @R|kotlin/ParameterName|(name = String(bar)) kotlin/Any) -> kotlin/Unit|>(Q|SomeKey|, <L> = set@fun <anonymous>(<unused var>: R|kotlin/String|, <unused var>: R|@R|kotlin/ParameterName|(name = String(bar)) kotlin/Any|): R|kotlin/Unit| <inline=NoInline> {
^@set Unit
}
)
R|<local>/m|.R|SubstitutionOverride</MyMap.set: R|kotlin/Unit|>|<R|(kotlin/String, @R|kotlin/ParameterName|(name = String(bar)) kotlin/Any) -> kotlin/Unit|>(Q|SomeKey|, fun <anonymous>(<unused var>: R|kotlin/String|, <unused var>: R|@R|kotlin/ParameterName|(name = String(bar)) kotlin/Any|): R|kotlin/Unit| <inline=NoInline> {
^ Unit
}
)
}
public final data class EditorData : R|kotlin/Any| {
public constructor(meta: R|MyMap<EditorData, kotlin/Any>|): R|EditorData| {
super<R|kotlin/Any|>()
}
public final val meta: R|MyMap<EditorData, kotlin/Any>| = R|<local>/meta|
public get(): R|MyMap<EditorData, kotlin/Any>|
public final operator fun component1(): R|MyMap<EditorData, kotlin/Any>|
public final fun copy(meta: R|MyMap<EditorData, kotlin/Any>| = this@R|/EditorData|.R|/EditorData.meta|): R|EditorData|
}
public abstract interface MyMap<Domain, V : R|kotlin/Any|> : R|kotlin/Any| {
public abstract operator fun <T : R|V|> set(k: R|Key<T, Domain>|, v: R|T|): R|kotlin/Unit|
}
public abstract interface Key<V : R|kotlin/Any|, in Domain> : R|kotlin/Any| {
}
public abstract interface EditorDataKey<T : R|kotlin/Any|> : R|Key<T, EditorData>| {
}
public final object SomeKey : R|EditorDataKey<kotlin/Function2<kotlin/String, @R|kotlin/ParameterName|(name = String(bar)) kotlin/Any, kotlin/Unit>>| {
private constructor(): R|SomeKey| {
super<R|kotlin/Any|>()
}
}
@@ -0,0 +1,18 @@
// ISSUE: KT-56714
fun test(m: MyMap<EditorData, Any>) {
m.set(SomeKey) { _, _ -> }
m[SomeKey] = { _, _ -> }
}
data class EditorData(val meta: MyMap<EditorData, Any>)
interface MyMap<Domain, V : Any> {
operator fun <T : V> set(k: Key<T, Domain>, v: T)
}
interface Key<V : Any, in Domain>
interface EditorDataKey<T : Any> : Key<T, EditorData>
object SomeKey : EditorDataKey<(String, bar: Any) -> Unit>
@@ -0,0 +1,11 @@
FILE: main.kt
public final class Some : R|kotlin/Any| {
public constructor(): R|Some| {
super<R|kotlin/Any|>()
}
public final fun test(handle: R|VarHandle|): R|kotlin/Unit| {
R|<local>/handle|.R|/VarHandle.set|(vararg(this@R|/Some|, Boolean(false)))
}
}
@@ -0,0 +1,11 @@
// FILE: VarHandle.java
public class VarHandle {
public void set(Object... args) {}
}
// FILE: main.kt
class Some {
fun test(handle: VarHandle) {
handle.set(this, false)
}
}
@@ -921,6 +921,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/overloadWithDefault.kt");
}
@Test
@TestMetadata("setWithTrailingLambda.kt")
public void testSetWithTrailingLambda() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/setWithTrailingLambda.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
@@ -957,6 +963,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/vararg.kt");
}
@Test
@TestMetadata("varargFromJava.kt")
public void testVarargFromJava() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/varargFromJava.kt");
}
@Test
@TestMetadata("varargOfLambdasWithReceiver.kt")
public void testVarargOfLambdasWithReceiver() throws Exception {
@@ -921,6 +921,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/overloadWithDefault.kt");
}
@Test
@TestMetadata("setWithTrailingLambda.kt")
public void testSetWithTrailingLambda() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/setWithTrailingLambda.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
@@ -957,6 +963,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/vararg.kt");
}
@Test
@TestMetadata("varargFromJava.kt")
public void testVarargFromJava() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/varargFromJava.kt");
}
@Test
@TestMetadata("varargOfLambdasWithReceiver.kt")
public void testVarargOfLambdasWithReceiver() throws Exception {
@@ -174,7 +174,7 @@ private fun BodyResolveComponents.getCallableReferenceAdaptation(
val fakeArguments = createFakeArgumentsForReference(function, expectedArgumentsCount, inputTypes, unboundReceiverCount)
// TODO: Use correct originScope
val argumentMapping = mapArguments(fakeArguments, function, originScope = null)
val argumentMapping = mapArguments(fakeArguments, function, originScope = null, callSiteIsOperatorCall = false)
if (argumentMapping.diagnostics.any { !it.applicability.isSuccess }) return null
/**
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
import org.jetbrains.kotlin.fir.isIntersectionOverride
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver
@@ -65,6 +64,7 @@ fun BodyResolveComponents.mapArguments(
arguments: List<FirExpression>,
function: FirFunction,
originScope: FirScope?,
callSiteIsOperatorCall: Boolean
): ArgumentMapping {
if (arguments.isEmpty() && function.valueParameters.isEmpty()) {
return EmptyArgumentMapping
@@ -87,7 +87,8 @@ fun BodyResolveComponents.mapArguments(
// If this is an indexed access set operator, it could have default values or a vararg parameter in the middle.
// For proper argument mapping, wrap the last one, which is supposed to be the updated value, as a named argument.
val isIndexedSetOperator = function is FirSimpleFunction
val isIndexedSetOperator = callSiteIsOperatorCall
&& function is FirSimpleFunction
&& function.isOperator
&& function.name == OperatorNameConventions.SET
&& function.origin !is FirDeclarationOrigin.DynamicScope
@@ -424,8 +424,12 @@ internal object MapArguments : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportDiagnostic(HiddenCandidate)
val function = symbol.fir
val mapping = context.bodyResolveComponents.mapArguments(callInfo.arguments, function, candidate.originScope)
val mapping = context.bodyResolveComponents.mapArguments(
callInfo.arguments,
function,
candidate.originScope,
callSiteIsOperatorCall = (callInfo.callSite as? FirFunctionCall)?.origin == FirFunctionCallOrigin.Operator
)
candidate.argumentMapping = mapping.toArgumentToParameterMapping()
candidate.numDefaults = mapping.numDefaults()
@@ -15,5 +15,5 @@ fun main() {
1.set(2, z = 1)
1[2] += 1
1.set(2, 1)
1.set(2, <!NO_VALUE_FOR_PARAMETER!>1)<!>
}