[FIR] Report ARGUMENT_TYPE_MISMATCH for nested array literals

^KT-61843 Fixed
This commit is contained in:
Ivan Kochurkin
2024-01-12 22:29:45 +01:00
committed by Space Team
parent aecf05c4ac
commit 2be9a341ca
5 changed files with 44 additions and 22 deletions
@@ -573,33 +573,48 @@ class FirCallResolver(
// We want to "desugar" array literal arguments to arrayOf, intArrayOf, floatArrayOf and other *arrayOf* calls
// so that we can properly complete them eventually.
// In order to find out what the expected type is, we need to run argument mapping.
// Array literals can be nested despite the fact they are not supported in annotation arguments.
// But we should traverse them all recursively to report type mismatches.
// For nested array literal, we need a new expected type obtained from the previous expected type (extract type of array element).
// We don't want to force full completion before the whole call is completed so that type variables are preserved.
// But we need to pass expectType to figure out the correct *arrayOf* function (because Array<T> and primitive arrays can't be matched).
val mapping = transformer.resolutionContext.bodyResolveComponents.mapArguments(
annotation.arguments, constructorSymbol.fir, originScope = null, callSiteIsOperatorCall = false,
)
val argumentsToParameters = mapping.toArgumentToParameterMapping()
annotation.replaceArgumentList(buildArgumentList {
source = annotation.argumentList.source
annotation.arguments.mapTo(arguments) { arg ->
val resolutionMode = if (arg.unwrapArgument() is FirArrayLiteral) {
(argumentsToParameters[arg]?.returnTypeRef as? FirResolvedTypeRef)?.let {
// Enabling expectedTypeMismatchIsReportedInChecker clarifies error messages:
// It will be reported single ARGUMENT_TYPE_MISMATCH on the array literal in checkApplicabilityForArgumentType
// instead of several TYPE_MISMATCH for every mismatched argument.
ResolutionMode.WithExpectedType(
it,
forceFullCompletion = false,
expectedTypeMismatchIsReportedInChecker = true
)
} ?: ResolutionMode.ContextDependent.Default
} else {
ResolutionMode.ContextDependent
}
arg.transformSingle(transformer, resolutionMode)
}
})
fun FirCall.transformArgumentList(getExpectedType: (FirExpression) -> FirTypeRef?) {
replaceArgumentList(
buildArgumentList {
source = argumentList.source
argumentList.arguments.mapTo(arguments) { arg ->
val unwrappedArgument = arg.unwrapArgument()
val expectedType = getExpectedType(arg)
val resolutionMode = if (unwrappedArgument is FirArrayLiteral && expectedType is FirResolvedTypeRef) {
unwrappedArgument.transformArgumentList {
// Trying to extract expected type for the next nested array literal
expectedType.coneType.arrayElementType()?.toFirResolvedTypeRef()
}
// Enabling expectedTypeMismatchIsReportedInChecker clarifies error messages:
// It will be reported single ARGUMENT_TYPE_MISMATCH on the array literal in checkApplicabilityForArgumentType
// instead of several TYPE_MISMATCH for every mismatched argument.
ResolutionMode.WithExpectedType(
expectedType,
forceFullCompletion = false,
expectedTypeMismatchIsReportedInChecker = true
)
} else {
ResolutionMode.ContextDependent
}
return@mapTo arg.transformSingle(transformer, resolutionMode)
}
}
)
}
annotation.transformArgumentList { argumentsToParameters[it]?.returnTypeRef }
} else {
annotation.replaceArgumentList(annotation.argumentList.transform(transformer, ResolutionMode.ContextDependent.Default))
}
@@ -238,7 +238,7 @@ fun Candidate.resolvePlainExpressionArgument(
if (expectedType == null) return
// TODO Remove when KT-61843 is fixed
// TODO: this check should be eliminated, KT-65085
if (argument is FirArrayLiteral && !argument.isResolved) return
val argumentType = argument.resolvedType
@@ -1,9 +1,12 @@
@Retention(AnnotationRetention.RUNTIME)
annotation class Anno(vararg val x: String, val y: String)
@Anno(x = [["a", "b"], ["a", "b"]], y = "a")
@Anno(x = <!ARGUMENT_TYPE_MISMATCH!>[["a", "b"], ["a", "b"]]<!>, y = "a")
fun foo1() {}
@Anno(x = <!ARGUMENT_TYPE_MISMATCH!>[[<!UNSUPPORTED!>["a"]<!>]]<!>, y = "b")
fun foo11() {}
@Anno(x = ["a", "b"], y = "a")
fun foo2() {}
@@ -4,6 +4,9 @@ annotation class Anno(vararg val x: String, val y: String)
@Anno(x = [<!TYPE_MISMATCH, TYPE_MISMATCH!>["a", "b"]<!>, <!TYPE_MISMATCH, TYPE_MISMATCH!>["a", "b"]<!>], y = "a")
fun foo1() {}
@Anno(x = [<!TYPE_MISMATCH, TYPE_MISMATCH!>[["a"]]<!>], y = "b")
fun foo11() {}
@Anno(x = ["a", "b"], y = "a")
fun foo2() {}
@@ -1,6 +1,7 @@
package
@Anno(x = {{"a", "b"}, {"a", "b"}}, y = "a") public fun foo1(): kotlin.Unit
@Anno(x = {{{"a"}}}, y = "b") public fun foo11(): kotlin.Unit
@Anno(x = {"a", "b"}, y = "a") public fun foo2(): kotlin.Unit
@Anno(x = {{"a"}, {"b"}}, y = "a") public fun foo3(): kotlin.Unit
@Anno(x = {"a", "b"}, y = "a") public fun foo4(): kotlin.Unit