FIR: Fix candidate receivers orders when choosing a context receiver

^KT-53257 Fixed
This commit is contained in:
Denis.Zharkov
2022-07-22 13:31:08 +02:00
committed by Space
parent 8299cec66b
commit 7f7e5c5975
8 changed files with 57 additions and 18 deletions
@@ -17182,6 +17182,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt");
}
@Test
@TestMetadata("receiversOrder.kt")
public void testReceiversOrder() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/receiversOrder.kt");
}
@Test
@TestMetadata("simpleCall.kt")
public void testSimpleCall() throws Exception {
@@ -200,7 +200,7 @@ object CheckContextReceivers : ResolutionStage() {
}?.takeUnless { it.isEmpty() } ?: return
val receiverGroups: List<List<ImplicitReceiverValue<*>>> =
context.bodyResolveContext.towerDataContext.towerDataElements.mapNotNull { towerDataElement ->
context.bodyResolveContext.towerDataContext.towerDataElements.asReversed().mapNotNull { towerDataElement ->
towerDataElement.implicitReceiver?.let(::listOf) ?: towerDataElement.contextReceiverGroup
}
@@ -0,0 +1,27 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
class A(val x: String)
var result = ""
context(A)
fun foo() {
result += x
}
fun A.bar() {
foo()
baz {
foo()
}
}
fun baz(a: A.() -> Unit) {
a(A("K"))
}
fun box(): String {
A("O").bar() // prints "1", "1" while "1", "2" is expected
return result
}
@@ -272,7 +272,7 @@ FILE fqName:<root> fileName:/iteratorOperator.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): <root>.CounterIterator declared in <root>.iterator'
CONSTRUCTOR_CALL 'public constructor <init> (_context_receiver_0: <root>.CounterConfig, counter: <root>.Counter) [primary] declared in <root>.CounterIterator' type=<root>.CounterIterator origin=null
_context_receiver_0: GET_VAR '_context_receiver_0: <root>.CounterConfig declared in <root>.iterator' type=<root>.CounterConfig origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.CounterConfig declared in <root>.iterator.<anonymous>' type=<root>.CounterConfig origin=null
counter: GET_VAR '<this>: <root>.Counter declared in <root>.iterator' type=<root>.Counter origin=null
FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
@@ -115,7 +115,7 @@ class CounterIterator : Iterator<Int> {
operator fun Counter.iterator(_context_receiver_0: CounterConfig): CounterIterator {
return with<CounterConfig, CounterIterator>(receiver = _context_receiver_0, block = local fun CounterConfig.<anonymous>(): CounterIterator {
return CounterIterator(_context_receiver_0 = _context_receiver_0, counter = <this>)
return CounterIterator(_context_receiver_0 = $this$with, counter = <this>)
}
)
}
@@ -60,9 +60,9 @@ FILE fqName:<root> fileName:/lazy.kt
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_1: GET_VAR '$this$with: <root>.Lazy<kotlin.CharSequence> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.CharSequence> origin=null
CALL 'public final fun test2 <T> (_context_receiver_0: <root>.Lazy<T of <root>.test2>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: kotlin.Int
<T>: kotlin.CharSequence
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.CharSequence> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.CharSequence> origin=null
CALL 'public final fun with <T, R> (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1<T of kotlin.StandardKt.with, R of kotlin.StandardKt.with>): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null
<T>: <root>.Lazy<kotlin.CharSequence>
<R>: kotlin.Unit
@@ -84,9 +84,9 @@ FILE fqName:<root> fileName:/lazy.kt
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_1: GET_VAR '$this$with: <root>.Lazy<kotlin.CharSequence> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.CharSequence> origin=null
CALL 'public final fun test2 <T> (_context_receiver_0: <root>.Lazy<T of <root>.test2>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: kotlin.CharSequence
<T>: kotlin.Int
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.CharSequence> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.CharSequence> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
CALL 'public final fun with <T, R> (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1<T of kotlin.StandardKt.with, R of kotlin.StandardKt.with>): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null
<T>: <root>.Lazy<T of <root>.f>
<R>: kotlin.Unit
@@ -105,9 +105,9 @@ FILE fqName:<root> fileName:/lazy.kt
$receiver: VALUE_PARAMETER name:$this$with type:<root>.Lazy<kotlin.Int>
BLOCK_BODY
CALL 'public final fun test2 <T> (_context_receiver_0: <root>.Lazy<T of <root>.test2>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: T of <root>.f
<T>: kotlin.Int
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<T of <root>.f> declared in <root>.f.<anonymous>' type=<root>.Lazy<T of <root>.f> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
CALL 'public final fun with <T, R> (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1<T of kotlin.StandardKt.with, R of kotlin.StandardKt.with>): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null
<T>: <root>.Lazy<<root>.Lazy<T of <root>.f>>
<R>: kotlin.Unit
@@ -126,9 +126,9 @@ FILE fqName:<root> fileName:/lazy.kt
$receiver: VALUE_PARAMETER name:$this$with type:<root>.Lazy<kotlin.Int>
BLOCK_BODY
CALL 'public final fun test2 <T> (_context_receiver_0: <root>.Lazy<T of <root>.test2>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: <root>.Lazy<T of <root>.f>
<T>: kotlin.Int
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<<root>.Lazy<T of <root>.f>> declared in <root>.f.<anonymous>' type=<root>.Lazy<<root>.Lazy<T of <root>.f>> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
CALL 'public final fun test3 <T> (_context_receiver_0: <root>.Lazy<<root>.Lazy<T of <root>.test3>>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: T of <root>.f
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
@@ -151,9 +151,9 @@ FILE fqName:<root> fileName:/lazy.kt
$receiver: VALUE_PARAMETER name:$this$with type:<root>.Lazy<<root>.Lazy<T of <root>.f>>
BLOCK_BODY
CALL 'public final fun test2 <T> (_context_receiver_0: <root>.Lazy<T of <root>.test2>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: kotlin.Int
<T>: <root>.Lazy<T of <root>.f>
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
_context_receiver_0: GET_VAR '$this$with: <root>.Lazy<<root>.Lazy<T of <root>.f>> declared in <root>.f.<anonymous>.<anonymous>' type=<root>.Lazy<<root>.Lazy<T of <root>.f>> origin=null
CALL 'public final fun test3 <T> (_context_receiver_0: <root>.Lazy<<root>.Lazy<T of <root>.test3>>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: T of <root>.f
$receiver: GET_VAR '$this$with: <root>.Lazy<kotlin.Int> declared in <root>.f.<anonymous>' type=<root>.Lazy<kotlin.Int> origin=null
@@ -15,7 +15,7 @@ fun <T : Any?> f(lazy1: Lazy<Int>, lazy2: Lazy<CharSequence>, lazyT: Lazy<T>, la
with<Lazy<Int>, Unit>(receiver = lazy1, block = local fun Lazy<Int>.<anonymous>() {
return with<Lazy<CharSequence>, Unit>(receiver = lazy2, block = local fun Lazy<CharSequence>.<anonymous>() {
test1(_context_receiver_0 = $this$with, _context_receiver_1 = $this$with)
$this$with.test2<Int>(_context_receiver_0 = $this$with)
$this$with.test2<CharSequence>(_context_receiver_0 = $this$with)
}
)
}
@@ -23,21 +23,21 @@ fun <T : Any?> f(lazy1: Lazy<Int>, lazy2: Lazy<CharSequence>, lazyT: Lazy<T>, la
with<Lazy<CharSequence>, Unit>(receiver = lazy2, block = local fun Lazy<CharSequence>.<anonymous>() {
return with<Lazy<Int>, Unit>(receiver = lazy1, block = local fun Lazy<Int>.<anonymous>() {
test1(_context_receiver_0 = $this$with, _context_receiver_1 = $this$with)
$this$with.test2<CharSequence>(_context_receiver_0 = $this$with)
$this$with.test2<Int>(_context_receiver_0 = $this$with)
}
)
}
)
with<Lazy<T>, Unit>(receiver = lazyT, block = local fun Lazy<T>.<anonymous>() {
return with<Lazy<Int>, Unit>(receiver = lazy1, block = local fun Lazy<Int>.<anonymous>() {
$this$with.test2<T>(_context_receiver_0 = $this$with)
$this$with.test2<Int>(_context_receiver_0 = $this$with)
}
)
}
)
with<Lazy<Lazy<T>>, Unit>(receiver = lazyLazyT, block = local fun Lazy<Lazy<T>>.<anonymous>() {
return with<Lazy<Int>, Unit>(receiver = lazy1, block = local fun Lazy<Int>.<anonymous>() {
$this$with.test2<Lazy<T>>(_context_receiver_0 = $this$with)
$this$with.test2<Int>(_context_receiver_0 = $this$with)
$this$with.test3<T>(_context_receiver_0 = $this$with)
}
)
@@ -45,7 +45,7 @@ fun <T : Any?> f(lazy1: Lazy<Int>, lazy2: Lazy<CharSequence>, lazyT: Lazy<T>, la
)
with<Lazy<Int>, Unit>(receiver = lazy1, block = local fun Lazy<Int>.<anonymous>() {
return with<Lazy<Lazy<T>>, Unit>(receiver = lazyLazyT, block = local fun Lazy<Lazy<T>>.<anonymous>() {
$this$with.test2<Int>(_context_receiver_0 = $this$with)
$this$with.test2<Lazy<T>>(_context_receiver_0 = $this$with)
$this$with.test3<T>(_context_receiver_0 = $this$with)
}
)
@@ -17182,6 +17182,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt");
}
@Test
@TestMetadata("receiversOrder.kt")
public void testReceiversOrder() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/receiversOrder.kt");
}
@Test
@TestMetadata("simpleCall.kt")
public void testSimpleCall() throws Exception {