diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java index aec53012a9e..34e985ed006 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java @@ -793,6 +793,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt"); } + @Test + @TestMetadata("contextReceiverMethod.kt") + public void testContextReceiverMethod() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt"); + } + @Test @TestMetadata("contextualFunctionConversion.kt") public void testContextualFunctionConversion() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/LightTreeFir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/LightTreeFir2IrTextTestGenerated.java index dde66762469..bfd824c7d5f 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/LightTreeFir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/LightTreeFir2IrTextTestGenerated.java @@ -793,6 +793,12 @@ public class LightTreeFir2IrTextTestGenerated extends AbstractLightTreeFir2IrTex runTest("compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt"); } + @Test + @TestMetadata("contextReceiverMethod.kt") + public void testContextReceiverMethod() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt"); + } + @Test @TestMetadata("contextualFunctionConversion.kt") public void testContextualFunctionConversion() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExpressionReceiver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExpressionReceiver.kt index 1fbce1dad13..0f8a21de487 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExpressionReceiver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExpressionReceiver.kt @@ -65,7 +65,7 @@ interface ExpressionReceiver : ReceiverValue { if (referenceExpression != null) { val descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, referenceExpression) - if (descriptor is ClassDescriptor) { + if (descriptor is ClassDescriptor && !referenceExpression.isContextClassReceiverReference(bindingContext)) { return ThisExpressionClassReceiver(descriptor.original, expression, type, original = null) } } else if (expression is KtSuperExpression) { @@ -78,5 +78,8 @@ interface ExpressionReceiver : ReceiverValue { return ExpressionReceiverImpl(expression, type, original = null) } + + private fun KtReferenceExpression.isContextClassReceiverReference(bindingContext: BindingContext): Boolean = + bindingContext[BindingContext.THIS_REFERENCE_TARGET, this]?.value is ContextClassReceiver } } diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.fir.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.fir.ir.txt new file mode 100644 index 00000000000..7c2160bbf44 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.fir.ir.txt @@ -0,0 +1,61 @@ +FILE fqName: fileName:/contextReceiverMethod.kt + CLASS CLASS name:Context modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Context + CONSTRUCTOR visibility:public <> () returnType:.Context [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Context modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN name:foo visibility:public modality:FINAL <> ($this:.Context) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.Context + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in .Context' + CONST Int type=kotlin.Int value=1 + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Test + FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.Context visibility:private [final] + CONSTRUCTOR visibility:public <> (_context_receiver_0:.Context) returnType:.Test [primary] + VALUE_PARAMETER name:_context_receiver_0 index:0 type:.Context + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + SET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.Context visibility:private [final]' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Test declared in .Test' type=.Test origin=null + value: GET_VAR '_context_receiver_0: .Context declared in .Test.' type=.Context origin=null + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN name:foo visibility:public modality:FINAL <> ($this:.Test) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.Test + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in .Test' + CONST Int type=kotlin.Int value=2 + FUN name:bar visibility:public modality:FINAL <> ($this:.Test) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Test + BLOCK_BODY + VAR name:x type:kotlin.Int [val] + CALL 'public final fun foo (): kotlin.Int declared in .Context' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.Context visibility:private [final]' type=.Context origin=null + receiver: GET_VAR ': .Test declared in .Test.bar' type=.Test origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.fir.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.fir.kt.txt new file mode 100644 index 00000000000..b7d74ae7434 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.fir.kt.txt @@ -0,0 +1,31 @@ +class Context { + constructor() /* primary */ { + super/*Any*/() + /* () */ + + } + + fun foo(): Int { + return 1 + } + +} + +class Test { + private /* final field */ val contextReceiverField0: Context + constructor(_context_receiver_0: Context) /* primary */ { + super/*Any*/() + .#contextReceiverField0 = _context_receiver_0 + /* () */ + + } + + fun foo(): Int { + return 2 + } + + fun bar() { + val x: Int = .#contextReceiverField0.foo() + } + +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.ir.txt new file mode 100644 index 00000000000..45e69e18032 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.ir.txt @@ -0,0 +1,61 @@ +FILE fqName: fileName:/contextReceiverMethod.kt + CLASS CLASS name:Context modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Context + CONSTRUCTOR visibility:public <> () returnType:.Context [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Context modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN name:foo visibility:public modality:FINAL <> ($this:.Context) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.Context + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in .Context' + CONST Int type=kotlin.Int value=1 + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Test + FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.Context visibility:private [final] + CONSTRUCTOR visibility:public <> (:.Context) returnType:.Test [primary] + VALUE_PARAMETER name: index:0 type:.Context + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + SET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.Context visibility:private [final]' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Test declared in .Test' type=.Test origin=null + value: GET_VAR ': .Context declared in .Test.' type=.Context origin=null + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN name:foo visibility:public modality:FINAL <> ($this:.Test) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.Test + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in .Test' + CONST Int type=kotlin.Int value=2 + FUN name:bar visibility:public modality:FINAL <> ($this:.Test) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Test + BLOCK_BODY + VAR name:x type:kotlin.Int [val] + CALL 'public final fun foo (): kotlin.Int declared in .Context' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD FIELD_FOR_CLASS_CONTEXT_RECEIVER name:contextReceiverField0 type:.Context visibility:private [final]' type=.Context origin=null + receiver: GET_VAR ': .Test declared in .Test.bar' type=.Test origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt new file mode 100644 index 00000000000..25bb518232d --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ContextReceivers + +class Context { + fun foo() = 1 +} + +context(Context) +class Test { + fun foo() = 2 + fun bar() { + val x = this@Context.foo() + } +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt.txt new file mode 100644 index 00000000000..96b3893d8f6 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt.txt @@ -0,0 +1,31 @@ +class Context { + constructor() /* primary */ { + super/*Any*/() + /* () */ + + } + + fun foo(): Int { + return 1 + } + +} + +class Test { + private /* final field */ val contextReceiverField0: Context + constructor(: Context) /* primary */ { + super/*Any*/() + .#contextReceiverField0 = + /* () */ + + } + + fun foo(): Int { + return 2 + } + + fun bar() { + val x: Int = .#contextReceiverField0.foo() + } + +} diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt index b6ff4e7bbeb..93af32c53ac 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt @@ -45,5 +45,4 @@ FILE fqName: fileName:/property.kt $this: CALL 'public abstract fun a (): kotlin.Int declared in .A' type=kotlin.Int origin=null $this: GET_VAR ': .A declared in .' type=.A origin=null other: CALL 'public abstract fun b (): kotlin.Int declared in .B' type=kotlin.Int origin=null - $this: TYPE_OP type=.B origin=IMPLICIT_CAST typeOperand=.B - GET_VAR ': .B declared in .' type=.A origin=null + $this: GET_VAR ': .B declared in .' type=.B origin=null diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/property.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/property.kt.txt index e6af267762c..61e590f02c5 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/property.kt.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/property.kt.txt @@ -10,5 +10,6 @@ interface B { val c: Int get(: A, : B): Int { - return .a().plus(other = /*as B */.b()) + return .a().plus(other = .b()) } + diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java index e419b8efddc..85263858561 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java @@ -793,6 +793,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/declarations/contextReceivers/compoundAssignmentOperators.kt"); } + @Test + @TestMetadata("contextReceiverMethod.kt") + public void testContextReceiverMethod() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt"); + } + @Test @TestMetadata("contextualFunctionConversion.kt") public void testContextualFunctionConversion() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/klib/KlibTextTestCaseGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/klib/KlibTextTestCaseGenerated.java index 964d942b322..af87948cb9b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/klib/KlibTextTestCaseGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/klib/KlibTextTestCaseGenerated.java @@ -613,6 +613,11 @@ public class KlibTextTestCaseGenerated extends AbstractKlibTextTestCase { runTest("compiler/testData/ir/irText/declarations/contextReceivers/class.kt"); } + @TestMetadata("contextReceiverMethod.kt") + public void testContextReceiverMethod() throws Exception { + runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextReceiverMethod.kt"); + } + @TestMetadata("contextualPrimaryConstructorWithParams.kt") public void testContextualPrimaryConstructorWithParams() throws Exception { runTest("compiler/testData/ir/irText/declarations/contextReceivers/contextualPrimaryConstructorWithParams.kt");