[FIR] Report ARGUMENT_TYPE_MISMATCH for nested array literals
^KT-61843 Fixed
This commit is contained in:
committed by
Space Team
parent
aecf05c4ac
commit
2be9a341ca
@@ -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
|
||||
|
||||
+4
-1
@@ -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() {}
|
||||
|
||||
|
||||
+3
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user