diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 868a168cf2b..08e26278934 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -10471,6 +10471,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/extensions/classObject.kt"); } + @Test + @TestMetadata("contextReceiver.kt") + public void testContextReceiver() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceiver.kt"); + } + @Test @TestMetadata("ExtensionFunctions.kt") public void testExtensionFunctions() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index 966083f477d..b80da074e26 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -162,7 +162,7 @@ public class BodyResolver { descriptor, localContext != null ? localContext.inferenceSession : null ), scope -> new LexicalScopeImpl( - scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceiver(), + scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceivers(), LexicalScopeKind.CONSTRUCTOR_HEADER ), localContext @@ -439,7 +439,7 @@ public class BodyResolver { ) { // Initializing a scope will report errors if any. new LexicalScopeImpl( - scopeForConstructorResolution, descriptor, true, null, LexicalScopeKind.CLASS_HEADER, + scopeForConstructorResolution, descriptor, true, Collections.emptyList(), LexicalScopeKind.CLASS_HEADER, new TraceBasedLocalRedeclarationChecker(trace, overloadChecker), new Function1() { @Override @@ -780,7 +780,7 @@ public class BodyResolver { LexicalScope originalScope, ConstructorDescriptor unsubstitutedPrimaryConstructor ) { - return new LexicalScopeImpl(originalScope, unsubstitutedPrimaryConstructor, false, null, + return new LexicalScopeImpl(originalScope, unsubstitutedPrimaryConstructor, false, Collections.emptyList(), LexicalScopeKind.DEFAULT_VALUE, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> { for (ValueParameterDescriptor valueParameter : unsubstitutedPrimaryConstructor.getValueParameters()) { @@ -863,7 +863,12 @@ public class BodyResolver { LexicalScope accessorDeclaringScope = c.getDeclaringScope(accessor); assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists"; LexicalScope headerScope = ScopeUtils.makeScopeForPropertyHeader(accessorDeclaringScope, descriptor); - return new LexicalScopeImpl(headerScope, descriptor, true, descriptor.getExtensionReceiverParameter(), + List implicitReceivers = new ArrayList<>(); + ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter(); + if (extensionReceiverParameter != null) { + implicitReceivers.add(extensionReceiverParameter); + } + return new LexicalScopeImpl(headerScope, descriptor, true, implicitReceivers, LexicalScopeKind.PROPERTY_ACCESSOR_BODY); } @@ -1023,7 +1028,7 @@ public class BodyResolver { KtProperty property = (KtProperty) function.getParent(); SourceElement propertySourceElement = KotlinSourceElementKt.toSourceElement(property); SyntheticFieldDescriptor fieldDescriptor = new SyntheticFieldDescriptor(accessorDescriptor, propertySourceElement); - innerScope = new LexicalScopeImpl(innerScope, functionDescriptor, true, null, + innerScope = new LexicalScopeImpl(innerScope, functionDescriptor, true, Collections.emptyList(), LexicalScopeKind.PROPERTY_ACCESSOR_BODY, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> { handler.addVariableDescriptor(fieldDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java index ea556caaf2e..b9d363cf568 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.scopes.*; import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; +import java.util.ArrayList; import java.util.List; public class FunctionDescriptorUtil { @@ -65,8 +66,17 @@ public class FunctionDescriptorUtil { @NotNull FunctionDescriptor descriptor, @NotNull LocalRedeclarationChecker redeclarationChecker ) { + List implicitReceivers = new ArrayList<>(); + ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter(); + if (descriptor.getExtensionReceiverParameter() != null) { + implicitReceivers.add(extensionReceiverParameter); + } + List contextReceiverParameters = descriptor.getContextReceiverParameters(); + if (!contextReceiverParameters.isEmpty()) { + implicitReceivers.addAll(contextReceiverParameters); + } return new LexicalScopeImpl( - outerScope, descriptor, true, descriptor.getExtensionReceiverParameter(), + outerScope, descriptor, true, implicitReceivers, LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationChecker, handler -> { for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DslScopeViolationCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DslScopeViolationCallChecker.kt index 9f785504950..fcb14773a62 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DslScopeViolationCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DslScopeViolationCallChecker.kt @@ -49,7 +49,8 @@ object DslScopeViolationCallChecker : CallChecker { ) { val receiversUntilOneFromTheCall = context.scope.parentsWithSelf - .mapNotNull { (it as? LexicalScope)?.implicitReceiver?.value } + .flatMap { (it as? LexicalScope)?.implicitReceivers ?: emptyList() } + .map { it.value } .takeWhile { it != callImplicitReceiver }.toList() if (receiversUntilOneFromTheCall.isEmpty()) return diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index dbd3046d809..25fbaa85ec7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -366,10 +366,8 @@ class NewResolutionOldInference( ) : ImplicitScopeTower { private val cache = HashMap() - override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? = - scope.implicitReceiver?.value?.let { - cache.getOrPut(it) { resolutionContext.transformToReceiverWithSmartCastInfo(it) } - } + override fun getImplicitReceivers(scope: LexicalScope): List = + scope.implicitReceivers.map { cache.getOrPut(it.value) { resolutionContext.transformToReceiverWithSmartCastInfo(it.value) } } override fun getNameForGivenImportAlias(name: Name): Name? = (resolutionContext.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 4ab01faf0ed..e2fecccc486 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -400,13 +400,8 @@ class PSICallResolver( override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter get() = this@PSICallResolver.implicitsResolutionFilter private val cache = HashMap() - override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? { - val implicitReceiver = scope.implicitReceiver ?: return null - - return cache.getOrPut(implicitReceiver) { - context.transformToReceiverWithSmartCastInfo(implicitReceiver.value) - } - } + override fun getImplicitReceivers(scope: LexicalScope): List = + scope.implicitReceivers.map { cache.getOrPut(it) { context.transformToReceiverWithSmartCastInfo(it.value) } } override fun getNameForGivenImportAlias(name: Name): Name? = (context.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt index 30a5c446534..bb9fe65c902 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt @@ -35,7 +35,7 @@ class ClassResolutionScopesSupport( private val getOuterScope: () -> LexicalScope ) { private fun scopeWithGenerics(parent: LexicalScope): LexicalScopeImpl { - return LexicalScopeImpl(parent, classDescriptor, false, null, LexicalScopeKind.CLASS_HEADER) { + return LexicalScopeImpl(parent, classDescriptor, false, emptyList(), LexicalScopeKind.CLASS_HEADER) { classDescriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) } } } @@ -69,7 +69,7 @@ class ClassResolutionScopesSupport( scopeWithGenerics, classDescriptor, true, - classDescriptor.thisAsReceiverParameter, + listOf(classDescriptor.thisAsReceiverParameter), LexicalScopeKind.CLASS_MEMBER_SCOPE ) } @@ -96,7 +96,7 @@ class ClassResolutionScopesSupport( val lexicalChainedScope = LexicalChainedScope.create( parentForNewScope, ownerDescriptor, isOwnerDescriptorAccessibleByLabel = false, - implicitReceiver = companionObjectDescriptor?.thisAsReceiverParameter, + implicitReceivers = listOfNotNull(companionObjectDescriptor?.thisAsReceiverParameter), kind = LexicalScopeKind.CLASS_INHERITANCE, classDescriptor.staticScope, classDescriptor.unsubstitutedInnerClassesScope, @@ -146,7 +146,7 @@ fun scopeForInitializerResolution( classDescriptor.scopeForMemberDeclarationResolution, parentDescriptor, false, - null, + emptyList(), LexicalScopeKind.CLASS_INITIALIZER ) { if (primaryConstructorParameters.isNotEmpty()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt index fd62192a745..2eff1e26158 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt @@ -50,7 +50,7 @@ class ValueParameterResolver( inferenceSession: InferenceSession? ) { val scopeForDefaultValue = - LexicalScopeImpl(declaringScope, declaringScope.ownerDescriptor, false, null, LexicalScopeKind.DEFAULT_VALUE) + LexicalScopeImpl(declaringScope, declaringScope.ownerDescriptor, false, listOf(), LexicalScopeKind.DEFAULT_VALUE) val contextForDefaultValue = ExpressionTypingContext.newContext( trace, scopeForDefaultValue, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt index 3e642619ac9..7860afb6337 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt @@ -37,7 +37,7 @@ import org.jetbrains.kotlin.types.TypeApproximator interface ImplicitScopeTower { val lexicalScope: LexicalScope - fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? + fun getImplicitReceivers(scope: LexicalScope): List fun getNameForGivenImportAlias(name: Name): Name? diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index a9daacefd42..06f8215a88d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -144,7 +144,7 @@ class TowerResolver { ) } - getImplicitReceiver(scope)?.let { + getImplicitReceivers(scope).forEach { addLevel( MemberScopeTowerLevel(this@createNonLocalLevels, it), it.mayFitForName(name) @@ -197,9 +197,9 @@ class TowerResolver { .process(scope.mayFitForName(name))?.let { return it } } - implicitScopeTower.getImplicitReceiver(scope) - ?.let { processImplicitReceiver(it, resolveExtensionsForImplicitReceiver) } - ?.let { return it } + implicitScopeTower.getImplicitReceivers(scope).forEach { rv -> + processImplicitReceiver(rv, resolveExtensionsForImplicitReceiver)?.let { return it } + } } else { TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope as ImportingScope)) .process(scope.mayFitForName(name))?.let { return it } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt index b502459d272..9002b63e74c 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt @@ -32,7 +32,7 @@ class LexicalChainedScope private constructor( parent: LexicalScope, override val ownerDescriptor: DeclarationDescriptor, override val isOwnerDescriptorAccessibleByLabel: Boolean, - override val implicitReceiver: ReceiverParameterDescriptor?, + override val implicitReceivers: List, override val kind: LexicalScopeKind, // NB. Here can be very special subtypes of MemberScope (e.g., DeprecatedMemberScope). // Please, do not leak them outside of LexicalChainedScope, because other parts of compiler are not ready to work with them @@ -74,8 +74,14 @@ class LexicalChainedScope private constructor( override fun printStructure(p: Printer) { p.println( - this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name, - " with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {" + this::class.java.simpleName, + ": ", + kind, + "; for descriptor: ", + ownerDescriptor.name, + " with implicitReceiver: ", + if (implicitReceivers.isEmpty()) "NONE" else implicitReceivers.joinToString { it.value.toString() }, + " {" ) p.pushIndent() @@ -105,13 +111,13 @@ class LexicalChainedScope private constructor( parent: LexicalScope, ownerDescriptor: DeclarationDescriptor, isOwnerDescriptorAccessibleByLabel: Boolean, - implicitReceiver: ReceiverParameterDescriptor?, + implicitReceivers: List, kind: LexicalScopeKind, vararg memberScopes: MemberScope?, isStaticScope: Boolean = false ): LexicalScope = LexicalChainedScope( - parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, implicitReceiver, kind, + parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, implicitReceivers, kind, listOfNonEmptyScopes(*memberScopes).toTypedArray(), isStaticScope ) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt index 1d2add35fd3..6d9a076971e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt @@ -23,7 +23,7 @@ class LexicalScopeImpl @JvmOverloads constructor( parent: HierarchicalScope, override val ownerDescriptor: DeclarationDescriptor, override val isOwnerDescriptorAccessibleByLabel: Boolean, - override val implicitReceiver: ReceiverParameterDescriptor?, + override val implicitReceivers: List, override val kind: LexicalScopeKind, redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING, initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {} @@ -37,8 +37,14 @@ class LexicalScopeImpl @JvmOverloads constructor( override fun printStructure(p: Printer) { p.println( - this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name, - " with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {" + this::class.java.simpleName, + ": ", + kind, + "; for descriptor: ", + ownerDescriptor.name, + " with implicitReceiver: ", + if (implicitReceivers.isEmpty()) "NONE" else implicitReceivers.joinToString { it.value.toString() }, + " {" ) p.pushIndent() diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalWritableScope.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalWritableScope.kt index 7142206f572..6be44fcfb0a 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalWritableScope.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/LexicalWritableScope.kt @@ -30,8 +30,8 @@ class LexicalWritableScope( override val kind: LexicalScopeKind ) : LexicalScopeStorage(parent, redeclarationChecker) { - override val implicitReceiver: ReceiverParameterDescriptor? - get() = null + override val implicitReceivers: List + get() = emptyList() private var canWrite: Boolean = true private var lastSnapshot: Snapshot? = null @@ -105,8 +105,14 @@ class LexicalWritableScope( override fun printStructure(p: Printer) { p.println( - this::class.java.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name, - " with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {" + this::class.java.simpleName, + ": ", + kind, + "; for descriptor: ", + ownerDescriptor.name, + " with implicitReceivers: ", + if (implicitReceivers.isEmpty()) "NONE" else implicitReceivers.joinToString { it.value.toString() }, + " {" ) p.pushIndent() diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java index 44450837a61..fc257c82cb6 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java @@ -20,10 +20,15 @@ import kotlin.Unit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.PropertyDescriptor; +import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors; import org.jetbrains.kotlin.utils.Printer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public final class ScopeUtils { private ScopeUtils() {} @@ -31,7 +36,7 @@ public final class ScopeUtils { @NotNull LexicalScope parent, @NotNull PropertyDescriptor propertyDescriptor ) { - return new LexicalScopeImpl(parent, propertyDescriptor, false, null, LexicalScopeKind.PROPERTY_HEADER, + return new LexicalScopeImpl(parent, propertyDescriptor, false, Collections.emptyList(), LexicalScopeKind.PROPERTY_HEADER, // redeclaration on type parameters should be reported early, see: DescriptorResolver.resolvePropertyDescriptor() LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> { @@ -47,7 +52,7 @@ public final class ScopeUtils { @NotNull LexicalScope propertyHeader, @NotNull PropertyDescriptor propertyDescriptor ) { - return new LexicalScopeImpl(propertyHeader, propertyDescriptor, false, null, LexicalScopeKind.PROPERTY_INITIALIZER_OR_DELEGATE); + return new LexicalScopeImpl(propertyHeader, propertyDescriptor, false, Collections.emptyList(), LexicalScopeKind.PROPERTY_INITIALIZER_OR_DELEGATE); } @NotNull @@ -55,8 +60,13 @@ public final class ScopeUtils { @NotNull LexicalScope parent, @NotNull VariableDescriptorWithAccessors variableDescriptor ) { + List implicitReceivers = new ArrayList<>(); + ReceiverParameterDescriptor extensionReceiverParameter = variableDescriptor.getExtensionReceiverParameter(); + if (extensionReceiverParameter != null) { + implicitReceivers.add(extensionReceiverParameter); + } // todo: very strange scope! - return new LexicalScopeImpl(parent, variableDescriptor, true, variableDescriptor.getExtensionReceiverParameter(), + return new LexicalScopeImpl(parent, variableDescriptor, true, implicitReceivers, LexicalScopeKind.PROPERTY_DELEGATE_METHOD ); } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt index 23ad9246d1a..5ae34be3060 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt @@ -36,7 +36,7 @@ interface LexicalScope : HierarchicalScope { val ownerDescriptor: DeclarationDescriptor val isOwnerDescriptorAccessibleByLabel: Boolean - val implicitReceiver: ReceiverParameterDescriptor? + val implicitReceivers: List val kind: LexicalScopeKind @@ -50,8 +50,8 @@ interface LexicalScope : HierarchicalScope { override val isOwnerDescriptorAccessibleByLabel: Boolean get() = false - override val implicitReceiver: ReceiverParameterDescriptor? - get() = null + override val implicitReceivers: List + get() = emptyList() override val kind: LexicalScopeKind get() = LexicalScopeKind.EMPTY diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt index 9fd2491c945..c8ec684acdb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt @@ -36,8 +36,8 @@ val HierarchicalScope.parents: Sequence * Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first */ fun LexicalScope.getImplicitReceiversHierarchy(): List = collectFromMeAndParent { - (it as? LexicalScope)?.implicitReceiver -} + (it as? LexicalScope)?.implicitReceivers +}.flatten() fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection = collectAllFromMeAndParent { if (it is LexicalScope && it.isOwnerDescriptorAccessibleByLabel && it.ownerDescriptor.name == labelName) { @@ -261,7 +261,7 @@ fun LexicalScope.replaceImportingScopes(importingScopeChain: ImportingScope?): L fun LexicalScope.createScopeForDestructuring(newReceiver: ReceiverParameterDescriptor?): LexicalScope { return LexicalScopeImpl( parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, - newReceiver, + listOfNotNull(newReceiver), LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING ) } @@ -324,7 +324,7 @@ class ErrorLexicalScope : LexicalScope { override val ownerDescriptor: DeclarationDescriptor = ErrorUtils.createErrorClass("") override val isOwnerDescriptorAccessibleByLabel: Boolean = false - override val implicitReceiver: ReceiverParameterDescriptor? = null + override val implicitReceivers: List = emptyList() override val kind: LexicalScopeKind = LexicalScopeKind.THROWING override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceiver.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceiver.fir.kt new file mode 100644 index 00000000000..77005ab5757 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceiver.fir.kt @@ -0,0 +1,18 @@ +class A { + fun h1() {} +} + +class B { + fun h2() {} +} + +fun B.foo() { + h1() + h2() +} + +context(A) +fun B.bar() { + h1() + h2() +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceiver.kt b/compiler/testData/diagnostics/tests/extensions/contextReceiver.kt new file mode 100644 index 00000000000..e597616d529 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceiver.kt @@ -0,0 +1,18 @@ +class A { + fun h1() {} +} + +class B { + fun h2() {} +} + +fun B.foo() { + h1() + h2() +} + +context(A) +fun B.bar() { + h1() + h2() +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceiver.txt b/compiler/testData/diagnostics/tests/extensions/contextReceiver.txt new file mode 100644 index 00000000000..ae57f37d81e --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceiver.txt @@ -0,0 +1,20 @@ +package + +public fun B.bar(): kotlin.Unit +public fun B.foo(): kotlin.Unit + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun h1(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun h2(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 961cffc1087..ef4200705cd 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -10477,6 +10477,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/extensions/classObject.kt"); } + @Test + @TestMetadata("contextReceiver.kt") + public void testContextReceiver() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceiver.kt"); + } + @Test @TestMetadata("ExtensionFunctions.kt") public void testExtensionFunctions() throws Exception { diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java index c5507e91362..671b109a52d 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java @@ -148,7 +148,7 @@ public class ExpectedResolveDataUtil { emptyModule.initialize(PackageFragmentProvider.Empty.INSTANCE); LexicalScopeImpl lexicalScope = new LexicalScopeImpl(ImportingScope.Empty.INSTANCE, classDescriptor, false, - classDescriptor.getThisAsReceiverParameter(), + Collections.singletonList(classDescriptor.getThisAsReceiverParameter()), LexicalScopeKind.SYNTHETIC); LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(environment.getConfiguration()); diff --git a/compiler/tests/org/jetbrains/kotlin/types/DefaultModalityModifiersTest.java b/compiler/tests/org/jetbrains/kotlin/types/DefaultModalityModifiersTest.java index 67a15e5c7f7..f6dcfba0e2b 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/DefaultModalityModifiersTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/DefaultModalityModifiersTest.java @@ -100,7 +100,7 @@ public class DefaultModalityModifiersTest extends KotlinTestWithEnvironment { DeclarationDescriptor classDescriptor = bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass); return new LexicalScopeImpl( - ScopeUtilsKt.memberScopeAsImportingScope(libraryScope), root, false, null, + ScopeUtilsKt.memberScopeAsImportingScope(libraryScope), root, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> { handler.addClassifierDescriptor((ClassifierDescriptor) classDescriptor); diff --git a/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java b/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java index ae7e22433ff..4db77e1c2a8 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java @@ -551,7 +551,7 @@ public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment { ); LexicalScope scope = new LexicalScopeImpl(scopeWithImports, scopeWithImports.getOwnerDescriptor(), false, - receiverParameterDescriptor, LexicalScopeKind.SYNTHETIC); + Collections.singletonList(receiverParameterDescriptor), LexicalScopeKind.SYNTHETIC); assertType(scope, expression, expectedType); } diff --git a/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java b/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java index 6ed9a1b88b5..a0e6a39e5e9 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/TypeSubstitutorTest.java @@ -48,6 +48,7 @@ import org.jetbrains.kotlin.tests.di.InjectionKt; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -90,7 +91,7 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment { LocalRedeclarationChecker redeclarationChecker = new ThrowingLocalRedeclarationChecker(new OverloadChecker(TypeSpecificityComparator.NONE.INSTANCE)); LexicalScope typeParameters = new LexicalScopeImpl( - topLevelScope, module, false, null, LexicalScopeKind.SYNTHETIC, + topLevelScope, module, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, redeclarationChecker, handler -> { for (TypeParameterDescriptor parameterDescriptor : contextClass.getTypeConstructor().getParameters()) { @@ -100,7 +101,7 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment { } ); return LexicalChainedScope.Companion.create( - typeParameters, module, false, null, LexicalScopeKind.SYNTHETIC, + typeParameters, module, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, contextClass.getDefaultType().getMemberScope(), module.getBuiltIns().getBuiltInsPackageScope() ); diff --git a/compiler/tests/org/jetbrains/kotlin/types/TypeUnifierTest.java b/compiler/tests/org/jetbrains/kotlin/types/TypeUnifierTest.java index 3b02d349020..18bfa87f00c 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/TypeUnifierTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/TypeUnifierTest.java @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.DummyTraces; import org.jetbrains.kotlin.test.KotlinTestWithEnvironment; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -197,7 +198,7 @@ public class TypeUnifierTest extends KotlinTestWithEnvironment { private TypeProjection makeType(String typeStr) { LexicalScope withX = new LexicalScopeImpl( builtinsImportingScope, module, - false, null, LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, + false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> { handler.addClassifierDescriptor(x); handler.addClassifierDescriptor(y); diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt index 912016caa49..e65d187682d 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt @@ -374,7 +374,7 @@ class LazyScriptDescriptor( outerScope, receiverClassDescriptor, true, - receiverClassDescriptor.thisAsReceiverParameter, + listOf(receiverClassDescriptor.thisAsReceiverParameter), LexicalScopeKind.CLASS_MEMBER_SCOPE ).addImportingScope( AllUnderImportScope.create(receiverClassDescriptor, emptyList()) diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplImplicitsExtensionsResolutionFilter.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplImplicitsExtensionsResolutionFilter.kt index d81fa21b62c..3815deda85c 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplImplicitsExtensionsResolutionFilter.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplImplicitsExtensionsResolutionFilter.kt @@ -41,8 +41,8 @@ class ReplImplicitsExtensionsResolutionFilter( ): Sequence { val processedReceivers = mutableSetOf() return scopes.map { scope -> - val receiver = (scope as? LexicalScope)?.implicitReceiver?.value - val keep = receiver?.let { + val receivers = (scope as? LexicalScope)?.implicitReceivers?.map { it.value } + val keep = receivers?.all { lock.read { when (val descriptorFqName = (it as? ImplicitClassReceiver)?.declarationDescriptor?.fqNameSafe?.asString()) { null -> true