[FIR] KT-54980 Fix resolvability of too few/too many type arguments
- If too few or too many type arguments were provided, they were all
thrown away in `TypeArgumentMapping`,
`FirCallCompletionResultsWriterTransformer`, and `KtFirCallResolver`.
The fix handles type arguments of the wrong arity more gracefully.
- Note for `TypeArgumentMapping`: Excess type arguments are not needed
for candidate resolution. Excess type arguments are still resolved
due to the handling in `FirCallCompletionResultsWriterTransformer`.
- Post-processing in `AllCandidatesResolver`: When all candidates are
resolved in `AllCandidatesResolver.getAllCandidates`, the function
builds a FIR file. During that resolution, the
`generic<String, String>` call (in example
`functionCallWithTooFewTypeArguments.kt`) is correctly marked as
inapplicable, but the missing type argument is inferred as an error
type. `firFile` then contains a function call
`generic<String, String, ERROR>` instead of `generic<String, String>`.
This call is still marked as inapplicable. Despite that, the
*subsequent* resolution by
`bodyResolveComponents.callResolve.collectAllCandidates` disregards
the call's inapplicability and resolves successfully into an
applicable candidate. This is because `CandidateFactory` doesn't make
any guarantees for already inapplicable calls. The fix adds
post-processing to `AllCandidatesResolver` to preserve candidate
inapplicability.
- Most tests that this commit changes had slightly different results due
to type arguments becoming resolvable.
- `wrongNumberOfTypeArguments.kt` and
`wrongNumberOfArgumentsInTypeAliasConstructor.kt`:
`ConeDiagnostic.toFirDiagnostics` prefers specific errors. Because
`ARGUMENT_TYPE_MISMATCH` is specific and `INAPPLICABLE_CANDIDATE` is
not, only the former is reported. I see no reason to pass an illegally
typed argument in either test, so the change reduces the errors to
`INAPPLICABLE_CANDIDATE`.
- `typeAliasSamAdapterConstructors2.fir.kt`: See KT-55007.
- Disable `mismatchTypeParameters` JS backend test due to its handling
of excess type arguments. See KT-55250.
^KT-54980 fixed
This commit is contained in:
committed by
teamcity
parent
d6a9235d05
commit
5f554d0065
+31
@@ -11,11 +11,15 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.InapplicableCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.tower.FirTowerResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
@@ -25,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
|
||||
class AllCandidatesResolver(private val firSession: FirSession) {
|
||||
private val scopeSession = ScopeSession()
|
||||
@@ -66,6 +71,7 @@ class AllCandidatesResolver(private val firSession: FirSession) {
|
||||
return bodyResolveComponents.context.withFile(firFile, bodyResolveComponents) {
|
||||
bodyResolveComponents.callResolver
|
||||
.collectAllCandidates(functionCall, calleeName, bodyResolveComponents.context.containers, resolutionContext)
|
||||
.apply { postProcessCandidates() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +90,7 @@ class AllCandidatesResolver(private val firSession: FirSession) {
|
||||
.resolveDelegatingConstructorCall(delegatedConstructorCall, constructedType, derivedClassLookupTag)
|
||||
bodyResolveComponents.collector.allCandidates
|
||||
.map { OverloadCandidate(it, isInBestCandidates = it in bodyResolveComponents.collector.bestCandidates()) }
|
||||
.apply { postProcessCandidates() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,4 +103,28 @@ class AllCandidatesResolver(private val firSession: FirSession) {
|
||||
element.parentsOfType<KtDeclaration>().map { it.resolveToFirSymbol(firResolveSession).fir }.toList().asReversed()
|
||||
bodyResolveComponents.context.containers.addAll(containingDeclarations)
|
||||
}
|
||||
|
||||
private fun List<OverloadCandidate>.postProcessCandidates() {
|
||||
forEach { it.preserveCalleeInapplicability() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-processes a candidate to carry the callee's inapplicability over into the candidate. Without this post-processing, an issue may
|
||||
* arise where [getAllCandidates] produces "applicable" candidates with inapplicable callee references.
|
||||
*
|
||||
* For example, a function call `generic<String, String>` of function `fun <A, B, C> generic() { }` is correctly marked as inapplicable
|
||||
* by the compiler (due to the missing type argument), but the `firFile` built during [getAllCandidates] will contain an inapplicable
|
||||
* function call `generic<String, String, ERROR>` (with the missing type argument inferred as an error type). The *subsequent*
|
||||
* resolution by `bodyResolveComponents.callResolver.collectAllCandidates` feeds this call to
|
||||
* [org.jetbrains.kotlin.fir.resolve.calls.CandidateFactory], which doesn't make any guarantees for inapplicable calls. Hence, the
|
||||
* resulting candidate is *not* marked as inapplicable and needs to be post-processed.
|
||||
*/
|
||||
private fun OverloadCandidate.preserveCalleeInapplicability() {
|
||||
val callSite = candidate.callInfo.callSite as? FirQualifiedAccess ?: return
|
||||
val calleeReference = callSite.calleeReference as? FirDiagnosticHolder ?: return
|
||||
val diagnostic = calleeReference.diagnostic as? ConeInapplicableCandidateError ?: return
|
||||
if (diagnostic.applicability != CandidateApplicability.INAPPLICABLE) return
|
||||
|
||||
candidate.addDiagnostic(InapplicableCandidate)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user