K2: Fix internal error in FIR2IR caused by PCLA + String interpolation

There's an implicit contract in PCLA that the statement-level call
should be postponed iff it has something to be postponed inside.

And that contract didn't work well for string interpolation containing
some postponed calls.

Thus, we haven't run a completion results writing for them properly,
thus leaving type parameters (K from synthetic call) for expression
types instead of an inferred substituted type.

In this commit, the contract was reversed to explicitly enumerate
the cases when it's safe to resolve the candidate outside PCLA session.

See the comments at `mightBeAnalyzedAndCompletedIndependently`.

^KT-65341 Fixed
This commit is contained in:
Denis.Zharkov
2024-01-29 15:17:04 +01:00
committed by Space Team
parent 3ba8256b8d
commit 66d8f471d9
27 changed files with 346 additions and 147 deletions
@@ -0,0 +1,10 @@
MODULE main
CLASS Kt65341Kt$nodeTransformer$1.class
K1
---
K2
invoke(LNodeTransformer1;)Lkotlin/Unit; [public, final]
K1
invoke(LNodeTransformer1;)V [public, final]
K2
---
@@ -0,0 +1,24 @@
// TARGET_BACKEND: JVM
// ISSUE: KT-65341
// JVM_ABI_K1_K2_DIFF: KT-65386
val nodeTransformer =
single {
fun getConstructorParameterValue(kParameter: String) {
if (true) {
throw java.lang.IllegalStateException("${kParameter!!}")
}
}
}
fun <Output> single(
singleConstructor: (NodeTransformer1<Output>) -> Output?
) {
}
class NodeTransformer1<Output>
fun box(): String {
// Just making sure that for the original case the whole compiler pipeline is successfully completed
return "OK"
}
@@ -0,0 +1,44 @@
// ISSUE: KT-65341
class Controller<K> {
fun yield(k: K) {}
}
fun <T> generate(lambda: Controller<T>.() -> Unit) {}
fun bar(x: String) {}
var v: String = "OK"
fun foo0(x: String?) {
generate {
bar("$v abc${x!!}")
yield("")
}
}
fun foo1(x: String?) {
generate {
bar("$v abc${when { x != null -> x else -> null}}")
yield("")
}
}
fun <E> id(e: E): E = e
fun foo2(x: String?) {
generate {
bar("$v abc${id(this)}")
yield("")
}
}
fun box(): String {
foo0(null)
foo1(null)
foo2(null)
return "OK"
}