[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:
Marco Pennekamp
2022-11-21 19:15:50 +01:00
committed by teamcity
parent d6a9235d05
commit 5f554d0065
56 changed files with 721 additions and 37 deletions
@@ -71,7 +71,10 @@ KtInapplicableCallCandidateInfo:
callableIdIfNonLocal = null
]
callableIdIfNonLocal = kotlin/collections/groupBy
typeArgumentsMapping = {}
typeArgumentsMapping = {
T -> (kotlin.collections.IndexedValue<kotlin.Int>),
K -> (kotlin.Int)
}
argumentMapping = {
{ (_, value) -> value } -> (KtVariableLikeSignature:
name = keySelector
@@ -111,7 +114,9 @@ KtInapplicableCallCandidateInfo:
callableIdIfNonLocal = null
]
callableIdIfNonLocal = /groupBy
typeArgumentsMapping = {}
typeArgumentsMapping = {
K -> (kotlin.collections.IndexedValue<kotlin.Int>)
}
argumentMapping = {
{ (_, value) -> value } -> (KtVariableLikeSignature:
name = keySelector
@@ -0,0 +1,20 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<null: OTHER_ERROR with generic>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(): kotlin.Unit
valueParameters = []
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (ERROR_TYPE),
B -> (ERROR_TYPE),
C -> (ERROR_TYPE)
}
argumentMapping = {}
isInBestCandidates = true
@@ -0,0 +1,5 @@
fun <A, B, C> generic() { }
fun foo() {
<expr>generic<String, String>()</expr>
}
@@ -0,0 +1,20 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INAPPLICABLE_CANDIDATE: Inapplicable candidate(s): fun <A, B, C> generic(): Unit>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(): kotlin.Unit
valueParameters = []
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (kotlin.String),
B -> (kotlin.String),
C -> (ERROR CLASS: Cannot infer argument for type parameter C)
}
argumentMapping = {}
isInBestCandidates = true
@@ -0,0 +1,58 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<null: OTHER_ERROR with generic>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(a: A, b: B, c: C): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: A
callableIdIfNonLocal = null,
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.String
symbol = b: B
callableIdIfNonLocal = null,
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: C
callableIdIfNonLocal = null
]
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (kotlin.String),
B -> (kotlin.String),
C -> (kotlin.String)
}
argumentMapping = {
"a" -> (KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: A
callableIdIfNonLocal = null),
"b" -> (KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.String
symbol = b: B
callableIdIfNonLocal = null),
"c" -> (KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: C
callableIdIfNonLocal = null)
}
isInBestCandidates = true
@@ -0,0 +1,5 @@
fun <A, B, C> generic(a: A, b: B, c: C) { }
fun foo() {
<expr>generic<String, String>("a", "b", "c")</expr>
}
@@ -0,0 +1,58 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INAPPLICABLE_CANDIDATE: Inapplicable candidate(s): fun <A, B, C> generic(a: A, b: B, c: C): Unit>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(a: A, b: B, c: C): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: A
callableIdIfNonLocal = null,
KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.String
symbol = b: B
callableIdIfNonLocal = null,
KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: C
callableIdIfNonLocal = null
]
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (kotlin.String),
B -> (kotlin.String),
C -> (kotlin.String)
}
argumentMapping = {
"a" -> (KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.String
symbol = a: A
callableIdIfNonLocal = null),
"b" -> (KtVariableLikeSignature:
name = b
receiverType = null
returnType = kotlin.String
symbol = b: B
callableIdIfNonLocal = null),
"c" -> (KtVariableLikeSignature:
name = c
receiverType = null
returnType = kotlin.String
symbol = c: C
callableIdIfNonLocal = null)
}
isInBestCandidates = true
@@ -0,0 +1,18 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<null: OTHER_ERROR with generic>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(): kotlin.Unit
valueParameters = []
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (ERROR_TYPE)
}
argumentMapping = {}
isInBestCandidates = true
@@ -0,0 +1,5 @@
fun <A> generic() { }
fun foo() {
<expr>generic<String, String>()</expr>
}
@@ -0,0 +1,18 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INAPPLICABLE_CANDIDATE: Inapplicable candidate(s): fun <A> generic(): Unit>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(): kotlin.Unit
valueParameters = []
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (kotlin.String)
}
argumentMapping = {}
isInBestCandidates = true
@@ -0,0 +1,32 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<null: OTHER_ERROR with generic>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(a: A): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Int
symbol = a: A
callableIdIfNonLocal = null
]
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (kotlin.Int)
}
argumentMapping = {
5 -> (KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Int
symbol = a: A
callableIdIfNonLocal = null)
}
isInBestCandidates = true
@@ -0,0 +1,5 @@
fun <A> generic(a: A) { }
fun foo() {
<expr>generic<Int, String>(5)</expr>
}
@@ -0,0 +1,32 @@
KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INAPPLICABLE_CANDIDATE: Inapplicable candidate(s): fun <A> generic(a: A): Unit>
candidate = KtSimpleFunctionCall:
isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
dispatchReceiver = null
extensionReceiver = null
signature = KtFunctionLikeSignature:
receiverType = null
returnType = kotlin.Unit
symbol = /generic(a: A): kotlin.Unit
valueParameters = [
KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Int
symbol = a: A
callableIdIfNonLocal = null
]
callableIdIfNonLocal = /generic
typeArgumentsMapping = {
A -> (kotlin.Int)
}
argumentMapping = {
5 -> (KtVariableLikeSignature:
name = a
receiverType = null
returnType = kotlin.Int
symbol = a: A
callableIdIfNonLocal = null)
}
isInBestCandidates = true