From 7f7e5c5975d8e30f2e1cd13202d4430740a1e609 Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Fri, 22 Jul 2022 13:31:08 +0200 Subject: [PATCH] FIR: Fix candidate receivers orders when choosing a context receiver ^KT-53257 Fixed --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++++ .../fir/resolve/calls/ResolutionStages.kt | 2 +- .../contextReceivers/receiversOrder.kt | 27 +++++++++++++++++++ .../iteratorOperator.fir.ir.txt | 2 +- .../iteratorOperator.fir.kt.txt | 2 +- .../contextReceivers/lazy.fir.ir.txt | 20 +++++++------- .../contextReceivers/lazy.fir.kt.txt | 10 +++---- .../IrBlackBoxCodegenTestGenerated.java | 6 +++++ 8 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 compiler/testData/codegen/box/extensionFunctions/contextReceivers/receiversOrder.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 393a0e4569b..b45438dedfe 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 89816bd09dd..4e2d0caf1fe 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -200,7 +200,7 @@ object CheckContextReceivers : ResolutionStage() { }?.takeUnless { it.isEmpty() } ?: return val receiverGroups: List>> = - context.bodyResolveContext.towerDataContext.towerDataElements.mapNotNull { towerDataElement -> + context.bodyResolveContext.towerDataContext.towerDataElements.asReversed().mapNotNull { towerDataElement -> towerDataElement.implicitReceiver?.let(::listOf) ?: towerDataElement.contextReceiverGroup } diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/receiversOrder.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/receiversOrder.kt new file mode 100644 index 00000000000..074966481ed --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/receiversOrder.kt @@ -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 +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.ir.txt index 198f37aa162..90d8b76568b 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.ir.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.ir.txt @@ -272,7 +272,7 @@ FILE fqName: fileName:/iteratorOperator.kt BLOCK_BODY RETURN type=kotlin.Nothing from='local final fun (): .CounterIterator declared in .iterator' CONSTRUCTOR_CALL 'public constructor (_context_receiver_0: .CounterConfig, counter: .Counter) [primary] declared in .CounterIterator' type=.CounterIterator origin=null - _context_receiver_0: GET_VAR '_context_receiver_0: .CounterConfig declared in .iterator' type=.CounterConfig origin=null + _context_receiver_0: GET_VAR '$this$with: .CounterConfig declared in .iterator.' type=.CounterConfig origin=null counter: GET_VAR ': .Counter declared in .iterator' type=.Counter origin=null FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.kt.txt index 7c22d442f0e..f66ae2152e5 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/iteratorOperator.fir.kt.txt @@ -115,7 +115,7 @@ class CounterIterator : Iterator { operator fun Counter.iterator(_context_receiver_0: CounterConfig): CounterIterator { return with(receiver = _context_receiver_0, block = local fun CounterConfig.(): CounterIterator { - return CounterIterator(_context_receiver_0 = _context_receiver_0, counter = ) + return CounterIterator(_context_receiver_0 = $this$with, counter = ) } ) } diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.ir.txt index 41c612c2a11..1fd6b7c0a90 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.ir.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.ir.txt @@ -60,9 +60,9 @@ FILE fqName: fileName:/lazy.kt _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null _context_receiver_1: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null CALL 'public final fun test2 (_context_receiver_0: .Lazy.test2>): kotlin.Unit declared in ' type=kotlin.Unit origin=null - : kotlin.Int + : kotlin.CharSequence $receiver: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null - _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null + _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null : .Lazy : kotlin.Unit @@ -84,9 +84,9 @@ FILE fqName: fileName:/lazy.kt _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null _context_receiver_1: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null CALL 'public final fun test2 (_context_receiver_0: .Lazy.test2>): kotlin.Unit declared in ' type=kotlin.Unit origin=null - : kotlin.CharSequence + : kotlin.Int $receiver: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null - _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null + _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null : .Lazy.f> : kotlin.Unit @@ -105,9 +105,9 @@ FILE fqName: fileName:/lazy.kt $receiver: VALUE_PARAMETER name:$this$with type:.Lazy BLOCK_BODY CALL 'public final fun test2 (_context_receiver_0: .Lazy.test2>): kotlin.Unit declared in ' type=kotlin.Unit origin=null - : T of .f + : kotlin.Int $receiver: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null - _context_receiver_0: GET_VAR '$this$with: .Lazy.f> declared in .f.' type=.Lazy.f> origin=null + _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null CALL 'public final fun with (receiver: T of kotlin.StandardKt.with, block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.StandardKt.with [inline] declared in kotlin.StandardKt' type=kotlin.Unit origin=null : .Lazy<.Lazy.f>> : kotlin.Unit @@ -126,9 +126,9 @@ FILE fqName: fileName:/lazy.kt $receiver: VALUE_PARAMETER name:$this$with type:.Lazy BLOCK_BODY CALL 'public final fun test2 (_context_receiver_0: .Lazy.test2>): kotlin.Unit declared in ' type=kotlin.Unit origin=null - : .Lazy.f> + : kotlin.Int $receiver: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null - _context_receiver_0: GET_VAR '$this$with: .Lazy<.Lazy.f>> declared in .f.' type=.Lazy<.Lazy.f>> origin=null + _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null CALL 'public final fun test3 (_context_receiver_0: .Lazy<.Lazy.test3>>): kotlin.Unit declared in ' type=kotlin.Unit origin=null : T of .f $receiver: GET_VAR '$this$with: .Lazy declared in .f..' type=.Lazy origin=null @@ -151,9 +151,9 @@ FILE fqName: fileName:/lazy.kt $receiver: VALUE_PARAMETER name:$this$with type:.Lazy<.Lazy.f>> BLOCK_BODY CALL 'public final fun test2 (_context_receiver_0: .Lazy.test2>): kotlin.Unit declared in ' type=kotlin.Unit origin=null - : kotlin.Int + : .Lazy.f> $receiver: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null - _context_receiver_0: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null + _context_receiver_0: GET_VAR '$this$with: .Lazy<.Lazy.f>> declared in .f..' type=.Lazy<.Lazy.f>> origin=null CALL 'public final fun test3 (_context_receiver_0: .Lazy<.Lazy.test3>>): kotlin.Unit declared in ' type=kotlin.Unit origin=null : T of .f $receiver: GET_VAR '$this$with: .Lazy declared in .f.' type=.Lazy origin=null diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.kt.txt index 5570a801fe6..ded18a94501 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/lazy.fir.kt.txt @@ -15,7 +15,7 @@ fun f(lazy1: Lazy, lazy2: Lazy, lazyT: Lazy, la with, Unit>(receiver = lazy1, block = local fun Lazy.() { return with, Unit>(receiver = lazy2, block = local fun Lazy.() { test1(_context_receiver_0 = $this$with, _context_receiver_1 = $this$with) - $this$with.test2(_context_receiver_0 = $this$with) + $this$with.test2(_context_receiver_0 = $this$with) } ) } @@ -23,21 +23,21 @@ fun f(lazy1: Lazy, lazy2: Lazy, lazyT: Lazy, la with, Unit>(receiver = lazy2, block = local fun Lazy.() { return with, Unit>(receiver = lazy1, block = local fun Lazy.() { test1(_context_receiver_0 = $this$with, _context_receiver_1 = $this$with) - $this$with.test2(_context_receiver_0 = $this$with) + $this$with.test2(_context_receiver_0 = $this$with) } ) } ) with, Unit>(receiver = lazyT, block = local fun Lazy.() { return with, Unit>(receiver = lazy1, block = local fun Lazy.() { - $this$with.test2(_context_receiver_0 = $this$with) + $this$with.test2(_context_receiver_0 = $this$with) } ) } ) with>, Unit>(receiver = lazyLazyT, block = local fun Lazy>.() { return with, Unit>(receiver = lazy1, block = local fun Lazy.() { - $this$with.test2>(_context_receiver_0 = $this$with) + $this$with.test2(_context_receiver_0 = $this$with) $this$with.test3(_context_receiver_0 = $this$with) } ) @@ -45,7 +45,7 @@ fun f(lazy1: Lazy, lazy2: Lazy, lazyT: Lazy, la ) with, Unit>(receiver = lazy1, block = local fun Lazy.() { return with>, Unit>(receiver = lazyLazyT, block = local fun Lazy>.() { - $this$with.test2(_context_receiver_0 = $this$with) + $this$with.test2>(_context_receiver_0 = $this$with) $this$with.test3(_context_receiver_0 = $this$with) } ) diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 4af22080465..8d09ad17a73 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -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 {