diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index b1dbc3dcc69..8a03082c040 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -36,10 +36,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirWhenSubjectImportingScope import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef -import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames.UNDERSCORE_FOR_UNUSED_VAR @@ -204,8 +201,8 @@ class BodyResolveContext( } @PrivateForInline - fun addReceiver(name: Name?, implicitReceiverValue: ImplicitReceiverValue<*>) { - replaceTowerDataContext(towerDataContext.addReceiver(name, implicitReceiverValue)) + fun addReceiver(name: Name?, implicitReceiverValue: ImplicitReceiverValue<*>, additionalLabelName: Name? = null) { + replaceTowerDataContext(towerDataContext.addReceiver(name, implicitReceiverValue, additionalLabelName)) } @PrivateForInline @@ -225,6 +222,7 @@ class BodyResolveContext( owner: FirCallableDeclaration, type: ConeKotlinType?, holder: SessionHolder, + additionalLabelName: Name? = null, f: () -> T ): T = withTowerDataCleanup { replaceTowerDataContext(towerDataContext.addContextReceiverGroup(owner.createContextReceiverValues(holder))) @@ -236,7 +234,7 @@ class BodyResolveContext( holder.session, holder.scopeSession ) - addReceiver(labelName, receiver) + addReceiver(labelName, receiver, additionalLabelName) } f() @@ -575,13 +573,19 @@ class BodyResolveContext( storeVariable(parameter, holder.session) } val receiverTypeRef = function.receiverTypeRef - withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f) + val type = receiverTypeRef?.coneType + val additionalLabelName = type?.labelName() + withLabelAndReceiverType(function.name, function, type, holder, additionalLabelName, f) } else { f() } } } + private fun ConeKotlinType.labelName(): Name? { + return (this as? ConeLookupTagBasedType)?.lookupTag?.name + } + @OptIn(PrivateForInline::class) fun forConstructorBody( constructor: FirConstructor, @@ -714,7 +718,9 @@ class BodyResolveContext( storeBackingField(property, holder.session) } withContainer(accessor) { - withLabelAndReceiverType(property.name, property, receiverTypeRef?.coneType, holder, f) + val type = receiverTypeRef?.coneType + val additionalLabelName = type?.labelName() + withLabelAndReceiverType(property.name, property, type, holder, additionalLabelName, f) } } } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ImplicitReceiverUtils.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ImplicitReceiverUtils.kt index 26af9d9a2d6..be0fe49eac3 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ImplicitReceiverUtils.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ImplicitReceiverUtils.kt @@ -168,11 +168,11 @@ class FirTowerDataContext private constructor( ) } - fun addReceiver(name: Name?, implicitReceiverValue: ImplicitReceiverValue<*>): FirTowerDataContext { + fun addReceiver(name: Name?, implicitReceiverValue: ImplicitReceiverValue<*>, additionalLabName: Name? = null): FirTowerDataContext { val element = implicitReceiverValue.asTowerDataElement() return FirTowerDataContext( towerDataElements.add(element), - implicitReceiverStack.add(name, implicitReceiverValue), + implicitReceiverStack.add(name, implicitReceiverValue, additionalLabName), localScopes, nonLocalTowerDataElements.add(element) ) diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt index 0b9e1e4dc7e..eff00f5f1d3 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt @@ -42,7 +42,7 @@ class PersistentImplicitReceiverStack private constructor( val stack = stack.add(value) val originalTypes = originalTypes.add(value.originalType) val index = stack.size - 1 - val receiversPerLabel = name?.let { receiversPerLabel.put(it, value) } ?: receiversPerLabel + val receiversPerLabel = receiversPerLabel.putIfNameIsNotNull(name, value).putIfNameIsNotNull(aliasLabel, value) val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index) return PersistentImplicitReceiverStack( @@ -53,6 +53,12 @@ class PersistentImplicitReceiverStack private constructor( ) } + private fun PersistentSetMultimap>.putIfNameIsNotNull(name: Name?, value: ImplicitReceiverValue<*>) = + if (name != null) + put(name, value) + else + this + fun addContextReceiver(value: ContextReceiverValue<*>): PersistentImplicitReceiverStack { val labelName = value.labelName ?: return this diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.fir.kt deleted file mode 100644 index e09d5221ac1..00000000000 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.fir.kt +++ /dev/null @@ -1,12 +0,0 @@ -// !LANGUAGE: +ContextReceivers -// WITH_STDLIB - -fun List.decimateEveryEvenThird() = sequence { - var counter = 1 - for (e in this@List) { - if (e % 2 == 0 && counter % 3 == 0) { - yield(e) - } - counter += 1 - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.kt index a0878c3deb3..9e9e468911e 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/fromKEEP/decimateEveryEvenThird.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +ContextReceivers // WITH_STDLIB diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.fir.kt deleted file mode 100644 index 673a2c54278..00000000000 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.fir.kt +++ /dev/null @@ -1,72 +0,0 @@ -// !LANGUAGE: +ContextReceivers - -class Param -class C { - val c = 42 -} -class R { - val r = 42 -} - -context(C) -fun R.f1(g: context(C) R.(Param) -> Unit) { - g(this@C, this@R, Param()) -} - -context(C) -fun f2(g: context(C) (Param) -> Unit) { - g(this@C, Param()) -} - -context(C) -fun R.f3(g: context(C) R.() -> Unit) { - g(this@C, this@R) -} - -context(C) -fun f4(g: context(C) () -> Unit) { - g(this@C) -} - -fun test() { - val lf1: context(C) R.(Param) -> Unit = { _ -> - r - c - } - val lf2: context(C) (Param) -> Unit = { _ -> - c - } - val lf3: context(C) R.() -> Unit = { - r - c - } - val lf4: context(C) () -> Unit = { - c - } - - with(C()) { - with(R()) { - f1(lf1) - f1 { _ -> - r - c - } - - f2(lf2) - f2 { _ -> - c - } - - f3(lf3) - f3 { - r - c - } - - f4(lf4) - f4 { - c - } - } - } -} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.kt index c41f82d32b0..42b4964d877 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/functionalType.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +ContextReceivers class Param diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/labelsFromClassNameForbidden.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/labelsFromClassNameForbidden.fir.kt index be6d6a56eac..631fe89c87b 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/labelsFromClassNameForbidden.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/labelsFromClassNameForbidden.fir.kt @@ -1,11 +1,11 @@ fun List.f() { - this@List.size + this@List.size } context(String) fun Int.f() { this@String.length - this@Int.toDouble() + this@Int.toDouble() } context(String) diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noLabelsByClassName.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noLabelsByClassName.fir.kt index 22725e03199..284bbc54ab0 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noLabelsByClassName.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noLabelsByClassName.fir.kt @@ -1,27 +1,27 @@ fun Int.f() { - this@Int + this@Int } var Int.p: Int get() { - this@Int + this@Int return@p 42 } set(value) { - this@Int + this@Int } class X { var Int.p: Int get() { - this@Int + this@Int return@p 42 } set(value) { - this@Int + this@Int } fun Int.f() { - this@Int + this@Int } } diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt index d4fc4295aeb..3cf9e983bf3 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt @@ -17,7 +17,7 @@ context(labelAInt@A, A, labelB@B) val C.p: Int this@A.a.length this@B this@labelB.b - this@C.c + this@C.c this@p.c this.c return 1 diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt index 48a91e53357..11888dc1791 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt @@ -23,7 +23,7 @@ context(A, A, B) fun f() { context(A, A, B) fun C.f() { this@A.a.length this@B.b - this@C.c + this@C.c this@f.c this.c } diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt index 1b683584a00..61001a91b14 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt @@ -37,7 +37,7 @@ context(A, A, B) val C.p: Int get() { this@A.a.length this@B.b - this@C.c + this@C.c this@p.c this.c return 1 diff --git a/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt index bdb6010bff1..b1af2a24c5e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt @@ -6,7 +6,7 @@ class Some { fun foo() { //this@foo this@Some - this@String + this@String } context(Some)