FIR: Fix leakage of type variables in builder inference for lambdas returning Unit

When BI/incomplete call is present in return argument, it will be
added to the main call-tree, leading to requirement violation in
`ConstraintSystemCompleter.getOrderedAllTypeVariables`
as after `FirBuilderInferenceSession.inferPostponedVariables` it will
be completed, and its type variables couldn't be found anymore

In K1, we actually do the same, but we are able to find type variables
of such calls due to architecture difference:
In K2, `getOrderedAllTypeVariables` uses FIR as the main source to
lookup
In K1, `getOrderedAllTypeVariables` uses resolution atom tree, where
candidate/CS of the call is still available after
`inferPostponedVariables`

In fact, all incomplete calls were analyzed in FULL mode according to
the contract of `FirBuilderInferenceSession.addPartiallyResolvedCall`.
Thus, it means we normally shouldn't add them to the main call-tree, but
accidentally do it as incomplete calls contain non-completed candidate

This particular commit addresses the problem partially, only
in cases when the expected return type for the lambda is Unit and when
the incomplete call is located in the last expression of the lambda

In such cases, we can skip the call from the last expression completely,
since all potential calls there were analyzed in FULL mode,
and couldn't introduce any useful info to the CS of the main call-tree

^KT-54294
This commit is contained in:
Simon Ogorodnik
2023-05-17 10:50:36 +00:00
committed by Space Team
parent ae1622d059
commit 3e6b42083b
17 changed files with 310 additions and 5 deletions
@@ -0,0 +1,43 @@
// FIR_IDENTICAL
// WITH_STDLIB
// SKIP_TXT
fun test1() =
buildBoxUnit {
set(select(Out(""), makeOut()))
mat() // Should be able to infer Unit here
}
fun test2() =
buildBoxProperType {
set(select(Out(""), makeOut()))
mat() // Should be able to infer String here
}
class Out<out V>(val v: V)
class Box<R> {
var boxed: R? = null
fun set(newValue: R) {
boxed = newValue
}
}
fun <R> buildBoxUnit(fill: Box<R>.() -> Unit): Box<R> {
return Box<R>().also {
it.fill()
}
}
fun <R> buildBoxProperType(fill: Box<R>.() -> String): Box<R> {
return Box<R>().also {
it.fill()
}
}
fun <S> select(a: S, b: S): S = a
fun <M> makeOut(): Out<M>? = null
fun <M> mat(): M = null!!