K2: Use Any? expected type only for the right argument of == operator

^KT-47409 Fixed
This commit is contained in:
Denis.Zharkov
2023-05-19 15:33:42 +02:00
committed by Space Team
parent 447e1711da
commit 6b2da2069d
3 changed files with 13 additions and 7 deletions
@@ -10,7 +10,7 @@ FILE: equals.kt
}
when () {
==(R|/materialize|<R|kotlin/Any?|>(), String()) -> {
==(R|/materialize<CS errors: /materialize>#|<<ERROR TYPE REF: Cannot infer argument for type parameter T>>(), String()) -> {
^main Unit
}
}
@@ -1,6 +1,7 @@
// ISSUE: KT-47409
fun <T> materialize(): T = TODO()
fun main() {
if ("" == materialize()) return // FE1.0: OK, type argument inferred to Any?
if (materialize() == "") return // FE1.0: Error, uninferred type argument for `T`
if (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materialize<!>() == "") return // FE1.0: Error, uninferred type argument for `T`
}
@@ -804,13 +804,18 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
equalityOperatorCall: FirEqualityOperatorCall,
data: ResolutionMode
): FirStatement = whileAnalysing(session, equalityOperatorCall) {
// Currently, we use expectedType=Any? for both operands
// In FE1.0, it's only used for the right
// But it seems a bit inconsistent (see KT-47409)
// Also it's kind of complicated to transform different arguments with different expectType considering current FIR structure
val arguments = equalityOperatorCall.argumentList.arguments
require(arguments.size == 2) {
"Unexpected number of arguments in equality call: ${arguments.size}"
}
// In cases like materialize1() == materialize2() we add expected type just for the right argument.
// One of the reasons is just consistency with K1 and with the desugared form `a.equals(b)`. See KT-47409 for clarifications.
val leftArgumentTransformed: FirExpression = arguments[0].transform(transformer, ResolutionMode.ContextIndependent)
val rightArgumentTransformed: FirExpression = arguments[1].transform(transformer, withExpectedType(builtinTypes.nullableAnyType))
equalityOperatorCall
.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
.replaceArgumentList(equalityOperatorCall.argumentList.transform(transformer, withExpectedType(builtinTypes.nullableAnyType)))
.replaceArgumentList(buildBinaryArgumentList(leftArgumentTransformed, rightArgumentTransformed))
equalityOperatorCall.resultType = equalityOperatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
dataFlowAnalyzer.exitEqualityOperatorCall(equalityOperatorCall)