[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
+24
@@ -297,6 +297,30 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithSpreadArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooFewTypeArguments.kt")
|
||||
public void testFunctionCallWithTooFewTypeArguments() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooFewTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooFewTypeArguments2.kt")
|
||||
public void testFunctionCallWithTooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooManyTypeArguments.kt")
|
||||
public void testFunctionCallWithTooManyTypeArguments() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooManyTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooManyTypeArguments2.kt")
|
||||
public void testFunctionCallWithTooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTypeArgument.kt")
|
||||
public void testFunctionCallWithTypeArgument() throws Exception {
|
||||
|
||||
+42
@@ -622,6 +622,48 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/TypeArgumentBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments2.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ValueParameter.kt")
|
||||
public void testValueParameter() throws Exception {
|
||||
|
||||
+14
-6
@@ -30,8 +30,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesRes
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
||||
@@ -798,21 +798,29 @@ internal class KtFirCallResolver(
|
||||
return toTypeArgumentsMapping(typeArguments, partiallyAppliedSymbol)
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps [typeArguments] to the type parameters of [partiallyAppliedSymbol].
|
||||
*
|
||||
* If too many type arguments are provided, a mapping is still created. Extra type arguments are simply ignored. If this wasn't the
|
||||
* case, the resulting [KtCall] would contain no type arguments at all, which can cause problems later. If too few type arguments are
|
||||
* provided, an empty map is returned defensively so that [toTypeArgumentsMapping] doesn't conjure any error types. If you want to map
|
||||
* too few type arguments meaningfully, please provide filler types explicitly.
|
||||
*/
|
||||
private fun toTypeArgumentsMapping(
|
||||
typeArguments: List<FirTypeProjection>,
|
||||
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
|
||||
): Map<KtTypeParameterSymbol, KtType> {
|
||||
val typeParameters = partiallyAppliedSymbol.symbol.typeParameters
|
||||
if (typeParameters.isEmpty()) return emptyMap()
|
||||
if (typeParameters.size != typeArguments.size) return emptyMap()
|
||||
if (typeArguments.size < typeParameters.size) return emptyMap()
|
||||
|
||||
val result = mutableMapOf<KtTypeParameterSymbol, KtType>()
|
||||
|
||||
for ((index, argument) in typeArguments.withIndex()) {
|
||||
for ((index, typeParameter) in typeParameters.withIndex()) {
|
||||
// After resolution all type arguments should be usual types (not FirPlaceholderProjection)
|
||||
if (argument !is FirTypeProjectionWithVariance || argument.variance != Variance.INVARIANT) return emptyMap()
|
||||
val argumentKtType = argument.typeRef.coneType.asKtType()
|
||||
result[typeParameters[index]] = argumentKtType
|
||||
val typeArgument = typeArguments[index]
|
||||
if (typeArgument !is FirTypeProjectionWithVariance || typeArgument.variance != Variance.INVARIANT) return emptyMap()
|
||||
result[typeParameter] = typeArgument.typeRef.coneType.asKtType()
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
+24
@@ -297,6 +297,30 @@ public class FirIdeNormalAnalysisSourceModuleResolveCandidatesTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithSpreadArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooFewTypeArguments.kt")
|
||||
public void testFunctionCallWithTooFewTypeArguments() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooFewTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooFewTypeArguments2.kt")
|
||||
public void testFunctionCallWithTooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooManyTypeArguments.kt")
|
||||
public void testFunctionCallWithTooManyTypeArguments() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooManyTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooManyTypeArguments2.kt")
|
||||
public void testFunctionCallWithTooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTypeArgument.kt")
|
||||
public void testFunctionCallWithTypeArgument() throws Exception {
|
||||
|
||||
+42
@@ -622,6 +622,48 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/TypeArgumentBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments2.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ValueParameter.kt")
|
||||
public void testValueParameter() throws Exception {
|
||||
|
||||
+42
@@ -622,6 +622,48 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/TypeArgumentBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments2.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ValueParameter.kt")
|
||||
public void testValueParameter() throws Exception {
|
||||
|
||||
+42
@@ -622,6 +622,48 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/TypeArgumentBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments2.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ValueParameter.kt")
|
||||
public void testValueParameter() throws Exception {
|
||||
|
||||
+24
@@ -297,6 +297,30 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCandidatesTestGenerat
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithSpreadArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooFewTypeArguments.kt")
|
||||
public void testFunctionCallWithTooFewTypeArguments() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooFewTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooFewTypeArguments2.kt")
|
||||
public void testFunctionCallWithTooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooManyTypeArguments.kt")
|
||||
public void testFunctionCallWithTooManyTypeArguments() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooManyTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTooManyTypeArguments2.kt")
|
||||
public void testFunctionCallWithTooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithTooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionCallWithTypeArgument.kt")
|
||||
public void testFunctionCallWithTypeArgument() throws Exception {
|
||||
|
||||
+42
@@ -622,6 +622,48 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/TypeArgumentBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooFewTypeArguments2.kt")
|
||||
public void testTypeArgument_tooFewTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooFewTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments1a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments1a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments1a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument_tooManyTypeArguments2a.kt")
|
||||
public void testTypeArgument_tooManyTypeArguments2a() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/typeArgument_tooManyTypeArguments2a.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ValueParameter.kt")
|
||||
public void testValueParameter() throws Exception {
|
||||
|
||||
+7
-2
@@ -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
|
||||
|
||||
+20
@@ -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
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun <A, B, C> generic() { }
|
||||
|
||||
fun foo() {
|
||||
<expr>generic<String, String>()</expr>
|
||||
}
|
||||
+20
@@ -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
|
||||
+58
@@ -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
|
||||
+5
@@ -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>
|
||||
}
|
||||
+58
@@ -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
|
||||
+18
@@ -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
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun <A> generic() { }
|
||||
|
||||
fun foo() {
|
||||
<expr>generic<String, String>()</expr>
|
||||
}
|
||||
+18
@@ -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
|
||||
+32
@@ -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
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun <A> generic(a: A) { }
|
||||
|
||||
fun foo() {
|
||||
<expr>generic<Int, String>(5)</expr>
|
||||
}
|
||||
+32
@@ -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
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// COMPILATION_ERRORS
|
||||
fun <A, B, C> generic() { }
|
||||
|
||||
fun foo() {
|
||||
generic<<caret>String, String>()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in kotlin) class String : kotlin.Comparable<kotlin.String>, kotlin.CharSequence, java.io.Serializable
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// COMPILATION_ERRORS
|
||||
interface X
|
||||
|
||||
fun <A, B, C> generic() { }
|
||||
|
||||
fun foo() {
|
||||
generic<String, <caret>X>()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in ROOT) interface X
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// COMPILATION_ERRORS
|
||||
fun <A, B, C> generic(a: A, b: B, c: C) { }
|
||||
|
||||
fun foo() {
|
||||
generic<<caret>String, String>("a", "b", "c")
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in kotlin) class String : kotlin.Comparable<kotlin.String>, kotlin.CharSequence, java.io.Serializable
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// COMPILATION_ERRORS
|
||||
interface X
|
||||
interface Y
|
||||
|
||||
fun <A> generic() { }
|
||||
|
||||
fun foo() {
|
||||
generic<X, <caret>Y>()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in ROOT) interface Y
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// COMPILATION_ERRORS
|
||||
interface X
|
||||
interface Y
|
||||
|
||||
fun <A> generic() { }
|
||||
|
||||
fun foo() {
|
||||
generic<<caret>X, Y>()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in ROOT) interface X
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// COMPILATION_ERRORS
|
||||
interface X
|
||||
|
||||
fun <A> generic(a: A) { }
|
||||
|
||||
fun foo() {
|
||||
generic<Int, <caret>X>(5)
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in ROOT) interface X
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// COMPILATION_ERRORS
|
||||
interface X
|
||||
|
||||
fun <A> generic(a: A) { }
|
||||
|
||||
fun foo() {
|
||||
generic<<caret>Int, X>(5)
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in kotlin) class Intprivate constructor : kotlin.Number(), kotlin.Comparable<kotlin.Int>, java.io.Serializable
|
||||
+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)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -24,9 +24,9 @@ FILE: typeArgumentsNotAllowed.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final val a: <ERROR TYPE REF: Unresolved name: MyClass> = Q|rest|.<Unresolved name: MyClass>#
|
||||
public final val a: <ERROR TYPE REF: Unresolved name: MyClass> = Q|rest|.<Unresolved name: MyClass>#<R|kotlin/String|>
|
||||
public get(): <ERROR TYPE REF: Unresolved name: MyClass>
|
||||
public final val b: <ERROR TYPE REF: Unresolved name: MyClass> = Q|rest/Best|.<Unresolved name: MyClass>#
|
||||
public final val b: <ERROR TYPE REF: Unresolved name: MyClass> = Q|rest/Best|.<Unresolved name: MyClass>#<R|kotlin/String|>
|
||||
public get(): <ERROR TYPE REF: Unresolved name: MyClass>
|
||||
public final class B<E> : R|kotlin/Any| {
|
||||
public constructor<E>(): R|rest/B<E>| {
|
||||
|
||||
+5
-5
@@ -58,21 +58,21 @@ FILE: propertyAccessWithExplicitTypeArguments.kt
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|>
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|>.R|/invoke|<R|kotlin/Int|, R|kotlin/String|>()
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|>
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|>
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|>
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|, R|kotlin/String|>
|
||||
R|<local>/receiver|.R|/hello1|<R|kotlin/Int|, R|kotlin/String|, R|kotlin/String|>
|
||||
R|kotlin/with|<R|ContextImpl<kotlin/String>|, R|kotlin/String|>(R|/ContextImpl.ContextImpl|<R|kotlin/String|>(), <L> = with@fun R|ContextImpl<kotlin/String>|.<anonymous>(): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
R|/hello2|<R|kotlin/String|>
|
||||
R|/hello2|<R|kotlin/String|>
|
||||
R|/hello2|<R|kotlin/String|>.R|/invoke|<R|kotlin/String|, R|kotlin/Int|>()
|
||||
R|/hello2|<R|kotlin/String|>
|
||||
R|/hello2|<R|kotlin/String|>
|
||||
R|/hello2|<R|kotlin/String|>
|
||||
R|/hello2|<R|kotlin/String|, R|kotlin/Int|>
|
||||
R|/hello2|<R|kotlin/String|, R|kotlin/Int|, R|kotlin/Int|>
|
||||
R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|>
|
||||
R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|>
|
||||
R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|>.R|/invoke|<R|kotlin/Int|, R|kotlin/String|>()
|
||||
R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|>
|
||||
R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|>
|
||||
^ R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|>
|
||||
^ R|<local>/receiver|.R|/hello3|<R|kotlin/Int|, R|kotlin/String|, R|kotlin/String|>
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+3
-2
@@ -14,8 +14,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.resolvedArgumentMapping
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.originalOrSelf
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Checks compatibility of variance of type argument for Java collections.
|
||||
@@ -53,7 +54,7 @@ object FirJavaGenericVarianceViolationTypeChecker : FirFunctionCallChecker() {
|
||||
}
|
||||
val argumentMapping = expression.resolvedArgumentMapping ?: return
|
||||
val typeArgumentMap = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
|
||||
for (i in 0 until expression.typeArguments.size) {
|
||||
for (i in 0 until min(expression.typeArguments.size, calleeFunction.typeParameterSymbols.size)) {
|
||||
val type = (expression.typeArguments[i] as? FirTypeProjectionWithVariance)?.typeRef?.coneType
|
||||
if (type != null) {
|
||||
typeArgumentMap[calleeFunction.typeParameterSymbols[i]] = type
|
||||
|
||||
@@ -43,6 +43,10 @@ class CandidateFactory private constructor(
|
||||
|
||||
constructor(context: ResolutionContext, callInfo: CallInfo) : this(context, buildBaseSystem(context, callInfo))
|
||||
|
||||
/**
|
||||
* [createCandidate] doesn't make any guarantees for inapplicable calls. Errors in the call or callee do not necessarily result in an
|
||||
* inapplicable [Candidate].
|
||||
*/
|
||||
fun createCandidate(
|
||||
callInfo: CallInfo,
|
||||
symbol: FirBasedSymbol<*>,
|
||||
|
||||
+4
-1
@@ -52,7 +52,10 @@ internal object MapTypeArguments : ResolutionStage() {
|
||||
) {
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments)
|
||||
} else {
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(emptyList())
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(
|
||||
if (typeArguments.size > owner.typeParameters.size) typeArguments.take(owner.typeParameters.size)
|
||||
else typeArguments
|
||||
)
|
||||
sink.yieldDiagnostic(InapplicableCandidate)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -513,7 +513,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
access: FirQualifiedAccess,
|
||||
candidate: Candidate
|
||||
): List<FirTypeProjection> {
|
||||
return computeTypeArgumentTypes(candidate)
|
||||
val typeArguments = computeTypeArgumentTypes(candidate)
|
||||
.mapIndexed { index, type ->
|
||||
when (val argument = access.typeArguments.getOrNull(index)) {
|
||||
is FirTypeProjectionWithVariance -> {
|
||||
@@ -540,6 +540,12 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We must ensure that all extra type arguments are preserved in the result, so that they can still be resolved later (e.g. for
|
||||
// navigation in the IDE).
|
||||
return if (typeArguments.size < access.typeArguments.size) {
|
||||
typeArguments + access.typeArguments.subList(typeArguments.size, access.typeArguments.size)
|
||||
} else typeArguments
|
||||
}
|
||||
|
||||
private fun computeTypeArgumentTypes(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// IGNORE_ERRORS
|
||||
// ERROR_POLICY: SEMANTIC
|
||||
// IGNORE_BACKEND_K2: JS_IR
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: t.kt
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
val u = <!UNRESOLVED_REFERENCE!>Unresolved<!>::class
|
||||
val g = <!UNRESOLVED_REFERENCE!>UnresolvedGeneric<!><UnresolvedTypeArg>::class
|
||||
@@ -1,2 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
val u = <!UNRESOLVED_REFERENCE!>Unresolved<!>::class
|
||||
val g = <!UNRESOLVED_REFERENCE!>UnresolvedGeneric<!><<!UNRESOLVED_REFERENCE!>UnresolvedTypeArg<!>>::class
|
||||
|
||||
+2
-2
@@ -10,6 +10,6 @@ fun test1() {
|
||||
|
||||
fun test2() {
|
||||
val m0 = java.util.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>HashMap<!>()
|
||||
val m1 = java.util.<!INAPPLICABLE_CANDIDATE!>HashMap<!><<!CANNOT_INFER_PARAMETER_TYPE!>String<!>, <!CANNOT_INFER_PARAMETER_TYPE!>String<!>, String>()
|
||||
val m2 = java.util.<!INAPPLICABLE_CANDIDATE!>HashMap<!><<!CANNOT_INFER_PARAMETER_TYPE!>String<!>>()
|
||||
val m1 = java.util.<!INAPPLICABLE_CANDIDATE!>HashMap<!><String, String, String>()
|
||||
val m2 = java.util.<!INAPPLICABLE_CANDIDATE!>HashMap<!><String>()
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fun box(): String {
|
||||
return <!INAPPLICABLE_CANDIDATE!>someFunction<!><<!CANNOT_INFER_PARAMETER_TYPE!>SomeEnum<!>>()
|
||||
return <!INAPPLICABLE_CANDIDATE!>someFunction<!><SomeEnum>()
|
||||
}
|
||||
|
||||
interface SomeInterface <V> {
|
||||
|
||||
+1
-1
@@ -6,4 +6,4 @@ class Outer {
|
||||
fun nested() = Outer.Nested<Int>()
|
||||
fun noArguments() = Outer.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Nested<!>()
|
||||
fun noArgumentsExpectedType(): Outer.Nested<String> = Outer.Nested()
|
||||
fun manyArguments() = Outer.<!INAPPLICABLE_CANDIDATE!>Nested<!><<!CANNOT_INFER_PARAMETER_TYPE!>String<!>, Int>()
|
||||
fun manyArguments() = Outer.<!INAPPLICABLE_CANDIDATE!>Nested<!><String, Int>()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
//KT-13330 AssertionError: Illegal resolved call to variable with invoke
|
||||
|
||||
fun foo(exec: (String.() -> Unit)?) = "".<!INAPPLICABLE_CANDIDATE!>exec<!><caret>() // <caret> is test data tag here
|
||||
fun foo(exec: (String.() -> Unit)?) = "".<!INAPPLICABLE_CANDIDATE!>exec<!><<!UNRESOLVED_REFERENCE!>caret<!>>() // <caret> is test data tag here
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
val unwrapped = <!UNRESOLVED_REFERENCE!>some<!><<!UNRESOLVED_REFERENCE!>sdf<!>()()<out Any>::unwrap
|
||||
val unwrapped = <!UNRESOLVED_REFERENCE!>some<!><<!UNRESOLVED_REFERENCE!>sdf<!>()()<<!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>out Any<!>>::unwrap
|
||||
|
||||
+2
-2
@@ -3,12 +3,12 @@
|
||||
fun <T> foo(t: T) = t
|
||||
|
||||
fun test1() {
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!><Int, String>("")
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!><Int, String>(0)
|
||||
}
|
||||
|
||||
|
||||
fun <T, R> bar(t: T, r: R) {}
|
||||
|
||||
fun test2() {
|
||||
<!INAPPLICABLE_CANDIDATE!>bar<!><Int>("", "")
|
||||
<!INAPPLICABLE_CANDIDATE!>bar<!><Int>(0, "")
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
fun <T> foo(t: T) = t
|
||||
|
||||
fun test1() {
|
||||
foo<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int, String><!>("")
|
||||
foo<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int, String><!>(0)
|
||||
}
|
||||
|
||||
|
||||
fun <T, R> bar(t: T, r: R) {}
|
||||
|
||||
fun test2() {
|
||||
bar<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>("", "")
|
||||
bar<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>(0, "")
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -20,10 +20,10 @@ val test2p2 = <!INAPPLICABLE_CANDIDATE!>P2<!><Int, Int>(1, 1)
|
||||
val test3p2 = <!INAPPLICABLE_CANDIDATE!>P2<!><Int, Int, Int>(1, 1)
|
||||
|
||||
val test0pr = PR(1, "")
|
||||
val test1pr = <!INAPPLICABLE_CANDIDATE!>PR<!><Int>(1, "")
|
||||
val test1pr = <!INAPPLICABLE_CANDIDATE!>PR<!><Int>("", 1)
|
||||
val test2pr = PR<Int, String>(<!ARGUMENT_TYPE_MISMATCH!>1<!>, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
val test2pra = PR<String, Int>(1, "")
|
||||
val test3pr = <!INAPPLICABLE_CANDIDATE!>P2<!><String, Int, Int>(1, "")
|
||||
val test3pr = <!INAPPLICABLE_CANDIDATE!>PR<!><String, Int, Int>(1, "")
|
||||
|
||||
class Num<T : Number>(val x: T)
|
||||
typealias N<T> = Num<T>
|
||||
|
||||
Vendored
+2
-2
@@ -20,10 +20,10 @@ val test2p2 = P2<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int, Int><!>(1, 1)
|
||||
val test3p2 = P2<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int, Int, Int><!>(1, 1)
|
||||
|
||||
val test0pr = PR(1, "")
|
||||
val test1pr = PR<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>(1, "")
|
||||
val test1pr = PR<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>("", 1)
|
||||
val test2pr = PR<Int, String>(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>, <!TYPE_MISMATCH!>""<!>)
|
||||
val test2pra = PR<String, Int>(1, "")
|
||||
val test3pr = P2<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><String, Int, Int><!>(1, "")
|
||||
val test3pr = PR<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><String, Int, Int><!>(1, "")
|
||||
|
||||
class Num<T : Number>(val x: T)
|
||||
typealias N<T> = Num<T>
|
||||
|
||||
Vendored
+2
-2
@@ -6,14 +6,14 @@ public val test0p2a: Pair<out kotlin.Any, out kotlin.Any>
|
||||
public val test0pr: PR<kotlin.String, kotlin.Int> /* = Pair<kotlin.Int, kotlin.String> */
|
||||
public val test1: P<kotlin.Int, kotlin.Int> /* = Pair<kotlin.Int, kotlin.Int> */
|
||||
public val test1p2: P2<kotlin.Int> /* = Pair<kotlin.Int, kotlin.Int> */
|
||||
public val test1pr: PR<kotlin.String, kotlin.Int> /* = Pair<kotlin.Int, kotlin.String> */
|
||||
public val test1pr: PR<kotlin.Int, kotlin.String> /* = Pair<kotlin.String, kotlin.Int> */
|
||||
public val test2: P<kotlin.Int, kotlin.Int> /* = Pair<kotlin.Int, kotlin.Int> */
|
||||
public val test2p2: P2<kotlin.Int> /* = Pair<kotlin.Int, kotlin.Int> */
|
||||
public val test2pr: PR<kotlin.Int, kotlin.String> /* = Pair<kotlin.String, kotlin.Int> */
|
||||
public val test2pra: PR<kotlin.String, kotlin.Int> /* = Pair<kotlin.Int, kotlin.String> */
|
||||
public val test3: P<kotlin.Int, kotlin.Int> /* = Pair<kotlin.Int, kotlin.Int> */
|
||||
public val test3p2: P2<kotlin.Int> /* = Pair<kotlin.Int, kotlin.Int> */
|
||||
public val test3pr: Pair<out kotlin.Any, out kotlin.Any>
|
||||
public val test3pr: PR<kotlin.String, kotlin.Int> /* = Pair<kotlin.Int, kotlin.String> */
|
||||
public val testMP0: MP<kotlin.Int> /* = MyPair<kotlin.String, kotlin.Int> */
|
||||
public val testMP1: MP<kotlin.String> /* = MyPair<kotlin.String, kotlin.String> */
|
||||
public val testMP2: MP<kotlin.String> /* = MyPair<kotlin.String, kotlin.String> */
|
||||
|
||||
Reference in New Issue
Block a user