diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 740b7066b3f..78a2a86081f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import kotlin.Pair; @@ -48,7 +49,6 @@ import org.jetbrains.kotlin.util.slicedMap.*; import java.util.Collection; import java.util.Collections; -import java.util.Map; import static org.jetbrains.kotlin.util.slicedMap.RewritePolicy.DO_NOTHING; import static org.jetbrains.kotlin.util.slicedMap.Slices.COMPILE_TIME_VALUE_REWRITE_POLICY; @@ -263,7 +263,7 @@ public interface BindingContext { .setFurtherLookupSlices(DECLARATIONS_TO_DESCRIPTORS) .build(); - WritableSlice> DESCRIPTOR_TO_NAMED_RECEIVERS = Slices.createSimpleSlice(); + WritableSlice> DESCRIPTOR_TO_NAMED_RECEIVERS = Slices.createSimpleSlice(); WritableSlice LABEL_TARGET = Slices.createSimpleSlice(); WritableSlice> AMBIGUOUS_LABEL_TARGET = Slices.createSimpleSlice(); WritableSlice VALUE_PARAMETER_AS_PROPERTY = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 43248fa4d1b..a6a877fcdb1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -16,7 +16,9 @@ package org.jetbrains.kotlin.resolve; +import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import kotlin.Pair; @@ -957,7 +959,7 @@ public class DescriptorResolver { } } - LinkedHashMap receiverToLabelMap = new LinkedHashMap<>(); + Multimap nameToReceiverMap = HashMultimap.create(); KtTypeReference receiverTypeRef = variableDeclaration.getReceiverTypeReference(); ReceiverParameterDescriptor receiverDescriptor = null; @@ -967,13 +969,16 @@ public class DescriptorResolver { receiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable( propertyDescriptor, receiverType, splitter.getAnnotationsForTarget(RECEIVER) ); - receiverToLabelMap.put(receiverDescriptor, receiverTypeRef.nameForReceiverLabel()); + String receiverName = receiverTypeRef.nameForReceiverLabel(); + if (receiverName != null) { + nameToReceiverMap.put(receiverName, receiverDescriptor); + } } List contextReceivers = variableDeclaration.getContextReceivers(); List contextReceiverDescriptors = createReceiverDescriptorsForProperty(propertyDescriptor, scopeForDeclarationResolutionWithTypeParameters, trace, - contextReceivers, receiverToLabelMap); + contextReceivers, nameToReceiverMap); LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeForInitializerResolutionWithTypeParameters, propertyDescriptor); KotlinType propertyType = propertyInfo.getVariableType(); @@ -1022,7 +1027,7 @@ public class DescriptorResolver { new FieldDescriptorImpl(annotationSplitter.getAnnotationsForTarget(FIELD), propertyDescriptor), new FieldDescriptorImpl(annotationSplitter.getAnnotationsForTarget(PROPERTY_DELEGATE_FIELD), propertyDescriptor) ); - trace.record(DESCRIPTOR_TO_NAMED_RECEIVERS, propertyDescriptor, receiverToLabelMap); + trace.record(DESCRIPTOR_TO_NAMED_RECEIVERS, propertyDescriptor, nameToReceiverMap); trace.record(BindingContext.VARIABLE, variableDeclaration, propertyDescriptor); return propertyDescriptor; } @@ -1032,7 +1037,7 @@ public class DescriptorResolver { @NotNull LexicalScope scopeForResolution, @NotNull BindingTrace trace, @NotNull List contextReceivers, - @NotNull Map receiverToLabelMap + @NotNull Multimap labelNameToReceiverMap ) { Map contextReceiversToTypes = new LinkedHashMap<>(); for (KtContextReceiver contextReceiver: contextReceivers) { @@ -1051,7 +1056,7 @@ public class DescriptorResolver { ); String contextReceiverName = contextReceiver.name(); if (contextReceiverName != null) { - receiverToLabelMap.put(receiverDescriptor, contextReceiverName); + labelNameToReceiverMap.put(contextReceiverName, receiverDescriptor); } return receiverDescriptor; }).collect(Collectors.toList()); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index 7a885039a77..7053f6868fa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.resolve +import com.google.common.collect.HashMultimap import com.intellij.openapi.util.ThrowableComputable import com.intellij.psi.PsiElement import com.intellij.util.AstLoadingFilter @@ -242,20 +243,20 @@ class FunctionDescriptorResolver( } if (languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) { - val receiverToLabelMap = linkedMapOf() + val labelNameToReceiverMap = HashMultimap.create() if (receiverTypeRef != null && extensionReceiver != null) { receiverTypeRef.nameForReceiverLabel()?.let { - receiverToLabelMap[extensionReceiver] = it + labelNameToReceiverMap.put(it, extensionReceiver) } } contextReceiverDescriptors.zip(0 until contextReceivers.size).reversed() .forEach { (contextReceiverDescriptor, i) -> contextReceivers[i].name()?.let { - receiverToLabelMap[contextReceiverDescriptor] = it + labelNameToReceiverMap.put(it, contextReceiverDescriptor) } } - trace.record(BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, functionDescriptor, receiverToLabelMap) + trace.record(BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, functionDescriptor, labelNameToReceiverMap) } functionDescriptor.initialize( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt index 0f24b1baff7..c9c02705bc1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt @@ -316,13 +316,13 @@ private fun findReceiverByLabelOrGetDefault( bindingContext: BindingContext, labelName: String ): ReceiverParameterDescriptor { - val receiverToLabelMap = bindingContext.get( + val labelNameToReceiverMap = bindingContext.get( BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, if (descriptorOfThisReceiver is PropertyAccessorDescriptor) descriptorOfThisReceiver.correspondingProperty else descriptorOfThisReceiver ) - return receiverToLabelMap?.entries?.find { - it.value == labelName - }?.key ?: default ?: error("'This' refers to the callable member without a receiver parameter: $descriptorOfThisReceiver") + return labelNameToReceiverMap?.get(labelName)?.singleOrNull() + ?: default + ?: error("'This' refers to the callable member without a receiver parameter: $descriptorOfThisReceiver") } private fun postfix(argumentInfo: IdentifierInfo, op: KtToken): IdentifierInfo = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt index 97a45912340..1ffce713b86 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt @@ -183,15 +183,13 @@ object LabelResolver { ) val declarationDescriptor = context.trace.bindingContext[DECLARATION_TO_DESCRIPTOR, element] if (declarationDescriptor is FunctionDescriptor) { - val receiverToLabelMap = context.trace.bindingContext[ + val labelNameToReceiverMap = context.trace.bindingContext[ DESCRIPTOR_TO_NAMED_RECEIVERS, if (declarationDescriptor is PropertyAccessorDescriptor) declarationDescriptor.correspondingProperty else declarationDescriptor ] - val thisReceivers = receiverToLabelMap?.entries?.filter { - it.value == labelName.identifier - }?.map { it.key } ?: emptyList() + val thisReceivers = labelNameToReceiverMap?.get(labelName.identifier) val thisReceiver = when { - thisReceivers.isEmpty() -> declarationDescriptor.extensionReceiverParameter + thisReceivers == null -> declarationDescriptor.extensionReceiverParameter thisReceivers.size == 1 -> thisReceivers.single() else -> { BindingContextUtils.reportAmbiguousLabel(context.trace, targetLabel, declarationsByLabel)