diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 78a2a86081f..6d3336c42dc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -263,7 +263,7 @@ public interface BindingContext { .setFurtherLookupSlices(DECLARATIONS_TO_DESCRIPTORS) .build(); - WritableSlice> DESCRIPTOR_TO_NAMED_RECEIVERS = Slices.createSimpleSlice(); + WritableSlice> DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP = 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 a6a877fcdb1..ce8ad158e1e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -959,8 +959,6 @@ public class DescriptorResolver { } } - Multimap nameToReceiverMap = HashMultimap.create(); - KtTypeReference receiverTypeRef = variableDeclaration.getReceiverTypeReference(); ReceiverParameterDescriptor receiverDescriptor = null; if (receiverTypeRef != null) { @@ -969,16 +967,38 @@ public class DescriptorResolver { receiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable( propertyDescriptor, receiverType, splitter.getAnnotationsForTarget(RECEIVER) ); - String receiverName = receiverTypeRef.nameForReceiverLabel(); - if (receiverName != null) { - nameToReceiverMap.put(receiverName, receiverDescriptor); - } } List contextReceivers = variableDeclaration.getContextReceivers(); - List contextReceiverDescriptors = - createReceiverDescriptorsForProperty(propertyDescriptor, scopeForDeclarationResolutionWithTypeParameters, trace, - contextReceivers, nameToReceiverMap); + List contextReceiverDescriptors = contextReceivers.stream() + .map(contextReceiver -> { + KtTypeReference typeReference = contextReceiver.typeReference(); + if (typeReference == null) { + return null; + } + KotlinType type = typeResolver.resolveType(scopeForDeclarationResolutionWithTypeParameters, typeReference, trace, true); + AnnotationSplitter splitter = new AnnotationSplitter(storageManager, type.getAnnotations(), EnumSet.of(RECEIVER)); + return DescriptorFactory.createContextReceiverParameterForCallable( + propertyDescriptor, type, splitter.getAnnotationsForTarget(RECEIVER) + ); + }).collect(Collectors.toList()); + + if (languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) { + Multimap nameToReceiverMap = HashMultimap.create(); + if (receiverTypeRef != null) { + String receiverName = receiverTypeRef.nameForReceiverLabel(); + if (receiverName != null) { + nameToReceiverMap.put(receiverName, receiverDescriptor); + } + } + for (int i = 0; i < contextReceivers.size(); i++) { + String contextReceiverName = contextReceivers.get(i).name(); + if (contextReceiverName != null) { + nameToReceiverMap.put(contextReceiverName, contextReceiverDescriptors.get(i)); + } + } + trace.record(DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, propertyDescriptor, nameToReceiverMap); + } LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeForInitializerResolutionWithTypeParameters, propertyDescriptor); KotlinType propertyType = propertyInfo.getVariableType(); @@ -1027,41 +1047,10 @@ public class DescriptorResolver { new FieldDescriptorImpl(annotationSplitter.getAnnotationsForTarget(FIELD), propertyDescriptor), new FieldDescriptorImpl(annotationSplitter.getAnnotationsForTarget(PROPERTY_DELEGATE_FIELD), propertyDescriptor) ); - trace.record(DESCRIPTOR_TO_NAMED_RECEIVERS, propertyDescriptor, nameToReceiverMap); trace.record(BindingContext.VARIABLE, variableDeclaration, propertyDescriptor); return propertyDescriptor; } - private List createReceiverDescriptorsForProperty( - @NotNull PropertyDescriptor propertyDescriptor, - @NotNull LexicalScope scopeForResolution, - @NotNull BindingTrace trace, - @NotNull List contextReceivers, - @NotNull Multimap labelNameToReceiverMap - ) { - Map contextReceiversToTypes = new LinkedHashMap<>(); - for (KtContextReceiver contextReceiver: contextReceivers) { - KtTypeReference typeReference = contextReceiver.typeReference(); - if (typeReference == null) { - continue; - } - KotlinType kotlinType = typeResolver.resolveType(scopeForResolution, typeReference, trace, true); - contextReceiversToTypes.put(contextReceiver, kotlinType); - } - return Lists.reverse(contextReceivers).stream().map(contextReceiver -> { - KotlinType receiverType = contextReceiversToTypes.get(contextReceiver); - AnnotationSplitter splitter = new AnnotationSplitter(storageManager, receiverType.getAnnotations(), EnumSet.of(RECEIVER)); - ReceiverParameterDescriptor receiverDescriptor = DescriptorFactory.createContextReceiverParameterForCallable( - propertyDescriptor, receiverType, splitter.getAnnotationsForTarget(RECEIVER) - ); - String contextReceiverName = contextReceiver.name(); - if (contextReceiverName != null) { - labelNameToReceiverMap.put(contextReceiverName, receiverDescriptor); - } - return receiverDescriptor; - }).collect(Collectors.toList()); - } - @NotNull /*package*/ static KotlinType transformAnonymousTypeIfNeeded( @NotNull DeclarationDescriptorWithVisibility descriptor, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index 7053f6868fa..8acdfabea3d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -256,7 +256,7 @@ class FunctionDescriptorResolver( } } - trace.record(BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, functionDescriptor, labelNameToReceiverMap) + trace.record(BindingContext.DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, 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 c9c02705bc1..118b74adddd 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 @@ -317,7 +317,7 @@ private fun findReceiverByLabelOrGetDefault( labelName: String ): ReceiverParameterDescriptor { val labelNameToReceiverMap = bindingContext.get( - BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, + BindingContext.DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, if (descriptorOfThisReceiver is PropertyAccessorDescriptor) descriptorOfThisReceiver.correspondingProperty else descriptorOfThisReceiver ) return labelNameToReceiverMap?.get(labelName)?.singleOrNull() 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 eee785f454b..7801defe363 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt @@ -185,7 +185,7 @@ object LabelResolver { val declarationDescriptor = context.trace.bindingContext[DECLARATION_TO_DESCRIPTOR, element] if (declarationDescriptor is FunctionDescriptor) { val labelNameToReceiverMap = context.trace.bindingContext[ - DESCRIPTOR_TO_NAMED_RECEIVERS, + DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, if (declarationDescriptor is PropertyAccessorDescriptor) declarationDescriptor.correspondingProperty else declarationDescriptor ] val thisReceivers = labelNameToReceiverMap?.get(labelName.identifier) diff --git a/compiler/testData/codegen/bytecodeListing/contextReceivers/property.txt b/compiler/testData/codegen/bytecodeListing/contextReceivers/property.txt index eb103a3ab11..50c5a42b5e1 100644 --- a/compiler/testData/codegen/bytecodeListing/contextReceivers/property.txt +++ b/compiler/testData/codegen/bytecodeListing/contextReceivers/property.txt @@ -13,5 +13,5 @@ public interface B { @kotlin.Metadata public final class PropertyKt { // source: 'property.kt' - public final static method getC(@org.jetbrains.annotations.NotNull p0: B, @org.jetbrains.annotations.NotNull p1: A): int + public final static method getC(@org.jetbrains.annotations.NotNull p0: A, @org.jetbrains.annotations.NotNull p1: B): int } diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.txt index faa36702f6d..c0b76062c3c 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.txt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.txt @@ -1,8 +1,8 @@ package context(A) public val a: kotlin.Int = 1 -context(B, A) public var b: kotlin.Int -context(B, A) public val c: kotlin.Int +context(A, B) public var b: kotlin.Int +context(A, B) public val c: kotlin.Int public interface A { public abstract fun a(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt index 553e558023d..056b158a091 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt @@ -1,6 +1,6 @@ package -context(B, A, A) public val C.p: kotlin.Int +context(A, A, B) public val C.p: kotlin.Int context(A, A, B) public fun f(): kotlin.Unit public final class A { diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt index 5685f4404f5..6c9bb77711c 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt @@ -1,8 +1,8 @@ package -context(B, A) public var p: kotlin.Int -context(B, A, A) public var p: kotlin.Int -context(B, A, A) public val C.p: kotlin.Int +context(A, A, B) public var p: kotlin.Int +context(A, B) public var p: kotlin.Int +context(A, A, B) public val C.p: kotlin.Int public final class A { public constructor A(/*0*/ a: T) diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt index cca6ebae399..b6ff4e7bbeb 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/property.ir.txt @@ -34,16 +34,16 @@ FILE fqName: fileName:/property.kt public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any PROPERTY name:c visibility:public modality:FINAL [val] - FUN name: visibility:public modality:FINAL <> (:.B, :.A) returnType:kotlin.Int + FUN name: visibility:public modality:FINAL <> (:.A, :.B) returnType:kotlin.Int correspondingProperty: PROPERTY name:c visibility:public modality:FINAL [val] contextReceiverParametersCount: 2 - VALUE_PARAMETER name: index:0 type:.B - VALUE_PARAMETER name: index:1 type:.A + VALUE_PARAMETER name: index:0 type:.A + VALUE_PARAMETER name: index:1 type:.B BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (: .B, : .A): kotlin.Int declared in ' + RETURN type=kotlin.Nothing from='public final fun (: .A, : .B): kotlin.Int declared in ' CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS $this: CALL 'public abstract fun a (): kotlin.Int declared in .A' type=kotlin.Int origin=null - $this: TYPE_OP type=.A origin=IMPLICIT_CAST typeOperand=.A - GET_VAR ': .A declared in .' type=.B 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: GET_VAR ': .B declared in .' type=.B origin=null + $this: TYPE_OP type=.B origin=IMPLICIT_CAST typeOperand=.B + GET_VAR ': .B declared in .' type=.A 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 b2625fe68f1..e6af267762c 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/property.kt.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/property.kt.txt @@ -9,6 +9,6 @@ interface B { } val c: Int - get(: B, : A): Int { - return /*as A */.a().plus(other = .b()) + get(: A, : B): Int { + return .a().plus(other = /*as B */.b()) } diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/property.txt b/compiler/testData/ir/irText/declarations/contextReceivers/property.txt deleted file mode 100644 index 5e6a4b042bf..00000000000 --- a/compiler/testData/ir/irText/declarations/contextReceivers/property.txt +++ /dev/null @@ -1,48 +0,0 @@ -FILE fqName: fileName:/property.kt - CLASS INTERFACE name:A modality:ABSTRACT visibility:public superTypes:[kotlin.Any] - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.A - FUN name:a visibility:public modality:ABSTRACT <> ($this:.A) returnType:kotlin.Int - $this: VALUE_PARAMETER name: type:.A - 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 INTERFACE name:B modality:ABSTRACT visibility:public superTypes:[kotlin.Any] - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.B - FUN name:b visibility:public modality:ABSTRACT <> ($this:.B) returnType:kotlin.Int - $this: VALUE_PARAMETER name: type:.B - 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 - PROPERTY name:c visibility:public modality:FINAL [val] - FUN name: visibility:public modality:FINAL <> (:.B, :.A) returnType:kotlin.Int - correspondingProperty: PROPERTY name:c visibility:public modality:FINAL [val] - VALUE_PARAMETER name: index:0 type:.B - VALUE_PARAMETER name: index:1 type:.A - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (: .B, : .A): kotlin.Int declared in ' - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS - $this: CALL 'public abstract fun a (): kotlin.Int declared in .A' type=kotlin.Int origin=null - $this: TYPE_OP type=.A origin=IMPLICIT_CAST typeOperand=.A - GET_VAR ': .A declared in .' type=.B origin=null - other: CALL 'public abstract fun b (): kotlin.Int declared in .B' type=kotlin.Int origin=null - $this: GET_VAR ': .B declared in .' type=.B origin=null diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.ir.txt b/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.ir.txt index 004d100042b..7f3093ebda3 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.ir.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.ir.txt @@ -111,13 +111,13 @@ FILE fqName: fileName:/thisWithCustomLabel.kt CALL 'public final fun (): kotlin.Any declared in .B' type=kotlin.Any origin=GET_PROPERTY $this: GET_VAR ': .B declared in .f' type=.B origin=null PROPERTY name:p visibility:public modality:FINAL [val] - FUN name: visibility:public modality:FINAL <> ($receiver:.C, :.B, :.A, :.A) returnType:kotlin.Int + FUN name: visibility:public modality:FINAL <> ($receiver:.C, :.A, :.A, :.B) returnType:kotlin.Int correspondingProperty: PROPERTY name:p visibility:public modality:FINAL [val] contextReceiverParametersCount: 3 $receiver: VALUE_PARAMETER name: type:.C - VALUE_PARAMETER name: index:0 type:.B + VALUE_PARAMETER name: index:0 type:.A VALUE_PARAMETER name: index:1 type:.A - VALUE_PARAMETER name: index:2 type:.A + VALUE_PARAMETER name: index:2 type:.B BLOCK_BODY TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null @@ -139,5 +139,5 @@ FILE fqName: fileName:/thisWithCustomLabel.kt TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public final fun (): kotlin.Any declared in .C' type=kotlin.Any origin=GET_PROPERTY $this: GET_VAR ': .C declared in .' type=.C origin=null - RETURN type=kotlin.Nothing from='public final fun (: .B, : .A, : .A): kotlin.Int declared in ' + RETURN type=kotlin.Nothing from='public final fun (: .A, : .A, : .B): kotlin.Int declared in ' CONST Int type=kotlin.Int value=1 diff --git a/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.kt.txt b/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.kt.txt index 23c5c9905d8..26dafd1f5cc 100644 --- a/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.kt.txt +++ b/compiler/testData/ir/irText/declarations/contextReceivers/thisWithCustomLabel.kt.txt @@ -44,7 +44,7 @@ fun f(: A, : A, : B) { } val C.p: Int - get(: B, : A, : A): Int { + get(: A, : A, : B): Int { .().toFloat() /*~> Unit */ .().() /*~> Unit */ .() /*~> Unit */