[FIR] Threat some error candidate applicabilities with same priority

There is a thing that `CandidateCollector` adds error candidate to the
  list of resulting candidates only if its applicability at least the
  same as current applicability of the collector

Also there is a problem, that deserialized symbol provider in CLI compiler
  and stub-based symbol provider in AA may return the same declarations
  in different order. This provokes the difference in the resulting set
  of candidates between the two modes:

```
val x by unresolved
```

During the resolution of this code compiler tries to find function `getValue`,
  and there are 6 of them in the stdlib. From them we are interseted in
  specific three:

1. `fun <K, V> Map<K, V>.getValue(key: R|K|): R|V|`
2. `inline operator fun <V, V1 : V> Map<in String, @Exact V>.getValue(thisRef: Any?, property: KProperty<*>): V1`
3. `inline operator fun <V, V1 : V> MutableMap<in String, out @Exact V>.getValue(thisRef: Any?, property: KProperty<*>): V1`

- (1) is inapplicable with `INAPPLICABLE_ARGUMENTS_MAPPING_ERROR`
- (2) and (3) are inapplicable with `INAPPLICABLE_WRONG_RECEIVER`
- `INAPPLICABLE_ARGUMENTS_MAPPING_ERROR` is more specific applicability than `INAPPLICABLE_WRONG_RECEIVER`
- CLI compiler always sees those functions in order 1 -> 2 -> 3
- AA providers sometimes returns them in order 2 -> 3 -> 1

So in CLI compilation candidates (2) and (3) are not added to the resulting
  set, as they are "less applicable" than (1), but in AA compilation they
  can be added to the set before (1), which causes sporadic change in
  FIR dump of `unsafeAssignmentExtra.kt`

To workaround this problem it was decided to treat `INAPPLICABLE_ARGUMENTS_MAPPING_ERROR`
  and `INAPPLICABLE_WRONG_RECEIVER` applicabilities as "equally specific"

^KT-65218 Fixed
This commit is contained in:
Dmitriy Novozhilov
2024-03-13 12:10:20 +02:00
committed by Space Team
parent d88092aa94
commit 30e2af7b66
3 changed files with 15 additions and 3 deletions
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerGroup
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability.INAPPLICABLE_ARGUMENTS_MAPPING_ERROR
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.resolve.calls.tower.shouldStopResolve
@@ -51,7 +53,17 @@ open class CandidateCollector(
bestGroup = group
}
if (applicability == currentApplicability && group == bestGroup) {
/*
* Here we would like to consider error candidates with `INAPPLICABLE_WRONG_RECEIVER` and `INAPPLICABLE_ARGUMENTS_MAPPING_ERROR` kinda
* "same error level". Generally it's questionable which candidates we should keep and which of those applicabilities is more
* specific and we should consider it during work on improvement of error reporting. But this particular check is needed
* to fix the KT-65218, which provoked by different stdlib declarations order in CLI compilation mode and AA mode (see
* the issue for more details)
*/
if (
(applicability == currentApplicability && group == bestGroup) ||
(currentApplicability == INAPPLICABLE_ARGUMENTS_MAPPING_ERROR && applicability == INAPPLICABLE_WRONG_RECEIVER)
) {
candidates.add(candidate)
}
@@ -8,6 +8,6 @@ class SomeClass
fun test(identifier: SomeClass, fn: String.() -> Unit) {
<!NONE_APPLICABLE!>identifier<!>()
<!NONE_APPLICABLE!>identifier<!>(123)
<!OPERATOR_MODIFIER_REQUIRED!>identifier<!>(<!ARGUMENT_TYPE_MISMATCH!>1<!>, <!TOO_MANY_ARGUMENTS!>2<!>)
<!NONE_APPLICABLE!>identifier<!>(1, 2)
1.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>fn<!>()
}
@@ -60,7 +60,7 @@ FILE: unsafeAssignmentExtra.fir.kt
}
}
lval x: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/getValue, kotlin/getValue, kotlin/getValue, kotlin/collections/getValue]>by this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|kotlin/Int|>|
lval x: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/getValue, kotlin/getValue, kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>by this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|kotlin/Int|>|
this@R|special/anonymous|.R|/change|<R|kotlin/Int|>(<L> = change@fun R|Foo<kotlin/Int>|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
this@R|special/anonymous|.R|SubstitutionOverride</Foo.a: R|kotlin/Int|>| = Int(99)
}