diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index f8278471226..60b8472c6f2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2692,35 +2692,45 @@ public class ExpressionCodegen extends KtVisitor impleme public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) { ResolvedCall resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext); - KotlinType receiverExpressionType = expressionJetType(expression.getReceiverExpression()); - Type receiverAsmType = receiverExpressionType != null ? asmType(receiverExpressionType) : null; - StackValue receiverValue = - receiverExpressionType != null ? StackValue.coercion(gen(expression.getReceiverExpression()), receiverAsmType) : null; + StackValue receiver = generateCallableReferenceReceiver(resolvedCall); FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); if (functionDescriptor != null) { - FunctionReferenceGenerationStrategy strategy = - new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null, false); + FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy( + state, functionDescriptor, resolvedCall, receiver != null ? receiver.type : null, null, false + ); return genClosure( expression, functionDescriptor, strategy, null, - (FunctionDescriptor) resolvedCall.getResultingDescriptor(), receiverValue + (FunctionDescriptor) resolvedCall.getResultingDescriptor(), receiver ); } - VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(expression); return generatePropertyReference( - expression, variableDescriptor, (VariableDescriptor) resolvedCall.getResultingDescriptor(), - receiverAsmType, receiverValue + expression, getVariableDescriptorNotNull(expression), + (VariableDescriptor) resolvedCall.getResultingDescriptor(), receiver ); } + @Nullable + private StackValue generateCallableReferenceReceiver(@NotNull ResolvedCall resolvedCall) { + CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); + if (descriptor.getExtensionReceiverParameter() == null && descriptor.getDispatchReceiverParameter() == null) return null; + + ReceiverValue dispatchReceiver = resolvedCall.getDispatchReceiver(); + ReceiverValue extensionReceiver = resolvedCall.getExtensionReceiver(); + assert dispatchReceiver == null || extensionReceiver == null : "Cannot generate reference with both receivers: " + descriptor; + ReceiverValue receiver = dispatchReceiver != null ? dispatchReceiver : extensionReceiver; + if (receiver == null || receiver instanceof TransientReceiver) return null; + + return StackValue.coercion(generateReceiverValue(receiver, false), asmType(receiver.getType())); + } + @NotNull private StackValue generatePropertyReference( @NotNull KtElement element, @NotNull VariableDescriptor variableDescriptor, @NotNull VariableDescriptor target, - @Nullable Type receiverAsmType, @Nullable StackValue receiverValue ) { ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor); @@ -2731,17 +2741,14 @@ public class ExpressionCodegen extends KtVisitor impleme element.getContainingFile() ); + Type receiverAsmType = receiverValue != null ? receiverValue.type : null; PropertyReferenceCodegen codegen = new PropertyReferenceCodegen( state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION), element, classBuilder, variableDescriptor, target, receiverAsmType ); codegen.generate(); - return codegen.putInstanceOnStack(receiverValue == null ? null : () -> { - assert receiverAsmType != null : "Receiver type should not be null when receiver value is not null: " + receiverValue; - receiverValue.put(receiverAsmType, v); - return Unit.INSTANCE; - }); + return codegen.putInstanceOnStack(receiverValue); } @NotNull @@ -3670,7 +3677,7 @@ public class ExpressionCodegen extends KtVisitor impleme // container class (where the PropertyReferenceNImpl instance is created), copy and adapt it at the call site //noinspection ConstantConditions StackValue value = context.getFunctionDescriptor().isInline() - ? generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null, null) + ? generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null) : PropertyCodegen.getDelegatedPropertyMetadata(variableDescriptor, bindingContext); value.put(K_PROPERTY_TYPE, v); metadataVar.storeSelector(K_PROPERTY_TYPE, v); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index f270b7e14d1..dab31527c17 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -165,7 +165,7 @@ class PropertyReferenceCodegen( writeSyntheticClassMetadata(v, state) } - fun putInstanceOnStack(receiverValue: (() -> Unit)?): StackValue { + fun putInstanceOnStack(receiverValue: StackValue?): StackValue { return StackValue.operation(wrapperMethod.returnType) { iv -> if (JvmCodegenUtil.isConst(closure)) { assert(receiverValue == null) { "No receiver expected for unbound property reference: $classDescriptor" } @@ -175,7 +175,7 @@ class PropertyReferenceCodegen( assert(receiverValue != null) { "Receiver expected for bound property reference: $classDescriptor" } iv.anew(asmType) iv.dup() - receiverValue!!() + receiverValue!!.put(receiverValue.type, iv) iv.invokespecial(asmType.internalName, "", constructor.descriptor, false) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index d8c91a060b3..bf17c9da8ce 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -57,6 +57,8 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.EnumValue; import org.jetbrains.kotlin.resolve.constants.NullValue; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; +import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.org.objectweb.asm.Type; @@ -332,12 +334,18 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { if (referencedFunction == null) return; CallableDescriptor target = referencedFunction.getResultingDescriptor(); + ReceiverValue extensionReceiver = referencedFunction.getExtensionReceiver(); + ReceiverValue dispatchReceiver = referencedFunction.getDispatchReceiver(); + + // TransientReceiver corresponds to an unbound reference, other receiver values -- to bound references + KotlinType receiverType = + dispatchReceiver != null && !(dispatchReceiver instanceof TransientReceiver) ? dispatchReceiver.getType() : + extensionReceiver != null && !(extensionReceiver instanceof TransientReceiver) ? extensionReceiver.getType() : + null; + CallableDescriptor callableDescriptor; Collection supertypes; - KtExpression receiverExpression = expression.getReceiverExpression(); - KotlinType receiverType = receiverExpression != null ? bindingContext.getType(receiverExpression) : null; - if (target instanceof FunctionDescriptor) { callableDescriptor = bindingContext.get(FUNCTION, expression); if (callableDescriptor == null) return;