diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index a42cc807b40..57ef1131956 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -513,12 +513,12 @@ public class AsmUtil { public static void genClosureFields(@NotNull CalculatedClosure closure, ClassBuilder v, KotlinTypeMapper typeMapper) { List> allFields = new ArrayList<>(); - ClassifierDescriptor captureThis = closure.getCaptureThis(); + ClassifierDescriptor captureThis = closure.getCapturedOuterClassDescriptor(); if (captureThis != null) { allFields.add(Pair.create(CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis))); } - KotlinType captureReceiverType = closure.getCaptureReceiverType(); + KotlinType captureReceiverType = closure.getCapturedReceiverFromOuterContext(); if (captureReceiverType != null && !CallableReferenceUtilKt.isForCallableReference(closure)) { allFields.add(Pair.create(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType))); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index cef8d63d22f..e7a30c97543 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -486,12 +486,12 @@ public class ClosureCodegen extends MemberCodegen { @NotNull Type ownerType ) { List args = Lists.newArrayList(); - ClassDescriptor captureThis = closure.getCaptureThis(); + ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor(); if (captureThis != null) { Type type = typeMapper.mapType(captureThis); args.add(FieldInfo.createForHiddenField(ownerType, type, CAPTURED_THIS_FIELD)); } - KotlinType captureReceiverType = closure.getCaptureReceiverType(); + KotlinType captureReceiverType = closure.getCapturedReceiverFromOuterContext(); if (captureReceiverType != null) { args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), CAPTURED_RECEIVER_FIELD)); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 8dcbea602a6..ba306d62a47 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1102,7 +1102,7 @@ public class ExpressionCodegen extends KtVisitor impleme int paramIndex = 0; if (putThis) { - ClassDescriptor captureThis = closure.getCaptureThis(); + ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor(); if (captureThis != null) { StackValue thisOrOuter = generateThisOrOuter(captureThis, false); assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type; @@ -1110,7 +1110,7 @@ public class ExpressionCodegen extends KtVisitor impleme } } - KotlinType captureReceiver = closure.getCaptureReceiverType(); + KotlinType captureReceiver = closure.getCapturedReceiverFromOuterContext(); if (captureReceiver != null) { StackValue capturedReceiver = functionReferenceReceiver != null ? functionReferenceReceiver : @@ -1135,7 +1135,7 @@ public class ExpressionCodegen extends KtVisitor impleme ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassNotAny(classDescriptor); if (superClass != null) { pushClosureOnStack( - superClass, putThis && closure.getCaptureThis() == null, callGenerator, /* functionReferenceReceiver = */ null + superClass, putThis && closure.getCapturedOuterClassDescriptor() == null, callGenerator, /* functionReferenceReceiver = */ null ); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 2d18408d629..9c0900ee859 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -668,14 +668,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } private void pushCapturedFieldsOnStack(InstructionAdapter iv, MutableClosure closure) { - ClassDescriptor captureThis = closure.getCaptureThis(); + ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor(); if (captureThis != null) { iv.load(0, classAsmType); Type type = typeMapper.mapType(captureThis); iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor()); } - KotlinType captureReceiver = closure.getCaptureReceiverType(); + KotlinType captureReceiver = closure.getCapturedReceiverFromOuterContext(); if (captureReceiver != null) { iv.load(0, classAsmType); Type type = typeMapper.mapType(captureReceiver); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 1c89f72f2e2..47b37769dbb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -86,10 +86,10 @@ public class JvmCodegenUtil { } public static boolean isConst(@NotNull CalculatedClosure closure) { - return closure.getCaptureThis() == null && - closure.getCaptureReceiverType() == null && - closure.getCaptureVariables().isEmpty() && - !closure.isSuspend(); + return closure.getCapturedOuterClassDescriptor() == null && + closure.getCapturedReceiverFromOuterContext() == null && + closure.getCaptureVariables().isEmpty() && + !closure.isSuspend(); } private static boolean isCallInsideSameClassAsFieldRepresentingProperty( @@ -259,7 +259,7 @@ public class JvmCodegenUtil { ) { //for compilation against sources if (closure != null) { - return closure.getCaptureThis(); + return closure.getCapturedOuterClassDescriptor(); } //for compilation against binaries diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index 0bb179bb223..c0ba7beb02f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -72,9 +72,9 @@ class PropertyReferenceCodegen( private val wrapperMethod = getWrapperMethodForPropertyReference(target, getFunction.valueParameters.size) private val closure = bindingContext.get(CodegenBinding.CLOSURE, classDescriptor)!!.apply { - assert((captureReceiverType != null) == (receiverType != null)) { + assert((capturedReceiverFromOuterContext != null) == (receiverType != null)) { "Bound property reference can only be generated with the type of the receiver. " + - "Captured type = $captureReceiverType, actual type = $receiverType" + "Captured type = $capturedReceiverFromOuterContext, actual type = $receiverType" } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java index 74f3fe5b477..161d8a58d22 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CalculatedClosure.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; +import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.org.objectweb.asm.Type; @@ -33,10 +34,13 @@ public interface CalculatedClosure { ClassDescriptor getClosureClass(); @Nullable - ClassDescriptor getCaptureThis(); + ClassDescriptor getCapturedOuterClassDescriptor(); @Nullable - KotlinType getCaptureReceiverType(); + KotlinType getCapturedReceiverFromOuterContext(); + + @NotNull + String getCapturedReceiverLabel(BindingContext bindingContext); @NotNull Map getCaptureVariables(); 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 3160c3fcacc..d18b1414507 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -403,7 +403,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { } if (receiverType != null) { - closure.setCaptureReceiverType(receiverType); + closure.setCustomCapturedReceiverType(receiverType); } super.visitCallableReferenceExpression(expression); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index f0110906aeb..7e2a5317fec 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -184,7 +184,7 @@ public class CodegenBinding { MutableClosure closure = new MutableClosure(classDescriptor, enclosing); if (classDescriptor.isInner()) { - closure.setCaptureThis(); + closure.setNeedsCaptureOuterClass(); } trace.record(ASM_TYPE, classDescriptor, asmType); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java index 43384eb012c..fe591d30041 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/MutableClosure.java @@ -19,8 +19,11 @@ package org.jetbrains.kotlin.codegen.binding; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.codegen.AsmUtil; import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.name.NameUtils; +import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.org.objectweb.asm.Type; @@ -73,16 +76,16 @@ public final class MutableClosure implements CalculatedClosure { } @Override - public ClassDescriptor getCaptureThis() { + public ClassDescriptor getCapturedOuterClassDescriptor() { return captureThis ? enclosingClass : null; } - public void setCaptureThis() { + public void setNeedsCaptureOuterClass() { this.captureThis = true; } @Override - public KotlinType getCaptureReceiverType() { + public KotlinType getCapturedReceiverFromOuterContext() { if (captureReceiverType != null) { return captureReceiverType; } @@ -96,23 +99,36 @@ public final class MutableClosure implements CalculatedClosure { return null; } - public void setCaptureReceiver() { + @NotNull + @Override + public String getCapturedReceiverLabel(BindingContext bindingContext) { + if (captureReceiverType != null) { + // Should effectively be returned only for callable references + return AsmUtil.CAPTURED_RECEIVER_FIELD; + } else if (enclosingFunWithReceiverDescriptor != null) { + return AsmUtil.CAPTURED_RECEIVER_FIELD; + } else { + throw new IllegalStateException("Closure does not capture an outer receiver"); + } + } + + public void setNeedsCaptureReceiverFromOuterContext() { if (enclosingFunWithReceiverDescriptor == null) { throw new IllegalStateException("Extension receiver parameter should exist"); } this.captureEnclosingReceiver = true; } + public void setCustomCapturedReceiverType(@NotNull KotlinType type) { + this.captureReceiverType = type; + } + @NotNull @Override public Map getCaptureVariables() { return captureVariables != null ? captureVariables : Collections.emptyMap(); } - public void setCaptureReceiverType(@NotNull KotlinType type) { - this.captureReceiverType = type; - } - @NotNull @Override public List> getRecordedFields() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/callableReferenceUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/callableReferenceUtil.kt index 6797297b257..66cd12edf40 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/callableReferenceUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/callableReferenceUtil.kt @@ -47,7 +47,7 @@ fun CalculatedClosure.isForCallableReference(): Boolean = closureClass.isSyntheticClassForCallableReference() fun CalculatedClosure.isForBoundCallableReference(): Boolean = - isForCallableReference() && captureReceiverType != null + isForCallableReference() && capturedReceiverFromOuterContext != null fun InstructionAdapter.loadBoundReferenceReceiverParameter(index: Int, type: Type) { load(index, type) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java index acfba5fbab2..76af3fa2dac 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java @@ -224,7 +224,7 @@ public abstract class CodegenContext { if (closure == null) { throw new IllegalStateException("Can't capture this for context without closure: " + this); } - closure.setCaptureThis(); + closure.setNeedsCaptureOuterClass(); } return StackValue.changeReceiverForFieldAndSharedVar(outerExpression.invoke(), prefix); } @@ -567,7 +567,7 @@ public abstract class CodegenContext { } if (myOuter != null && resultValue != null && !isStaticField(resultValue)) { - closure.setCaptureThis(); + closure.setNeedsCaptureOuterClass(); } return resultValue; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ConstructorContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ConstructorContext.java index 30010764b5e..bed153cc044 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ConstructorContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ConstructorContext.java @@ -40,7 +40,7 @@ public class ConstructorContext extends MethodContext { @Override public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) { - StackValue stackValue = closure != null && closure.getCaptureThis() != null ? LOCAL_1 : null; + StackValue stackValue = closure != null && closure.getCapturedOuterClassDescriptor() != null ? LOCAL_1 : null; if (!ignoreNoOuter && stackValue == null) { throw new UnsupportedOperationException("Don't know how to generate outer expression for " + getContextDescriptor()); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java index 3ef03da2c78..7819f9cc790 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/LocalLookup.java @@ -138,16 +138,19 @@ public interface LocalLookup { MutableClosure closure, Type classType ) { - if (closure.getEnclosingReceiverDescriptor() != d) { + ReceiverParameterDescriptor enclosingReceiverDescriptor = closure.getEnclosingReceiverDescriptor(); + if (enclosingReceiverDescriptor != d) { return null; } - KotlinType receiverType = closure.getEnclosingReceiverDescriptor().getType(); + assert(enclosingReceiverDescriptor != null); + + KotlinType receiverType = enclosingReceiverDescriptor.getType(); Type type = state.getTypeMapper().mapType(receiverType); StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field( type, receiverType, classType, CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0, d ); - closure.setCaptureReceiver(); + closure.setNeedsCaptureReceiverFromOuterContext(); return innerValue; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index 11dc5feb640..de1e4a78c3b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -570,7 +570,8 @@ class CoroutineCodegenForNamedFunction private constructor( codegen.v ) - val captureThisType = closure.captureThis?.let(typeMapper::mapType) + val captureThis = closure.capturedOuterClassDescriptor + val captureThisType = captureThis?.let(typeMapper::mapType) if (captureThisType != null) { StackValue.field( captureThisType, Type.getObjectType(v.thisName), AsmUtil.CAPTURED_THIS_FIELD, @@ -666,7 +667,7 @@ class CoroutineCodegenForNamedFunction private constructor( ].sure { "There must be a jvm view defined for $originalSuspendDescriptor" } if (suspendFunctionView.dispatchReceiverParameter != null) { - closure.setCaptureThis() + closure.setNeedsCaptureOuterClass() } return CoroutineCodegenForNamedFunction( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index b8e2e05f942..462afa2ea47 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -251,8 +251,9 @@ class PsiExpressionLambda( override val capturedVars: List by lazy { arrayListOf().apply { - if (closure.captureThis != null) { - val type = typeMapper.mapType(closure.captureThis!!) + val captureThis = closure.capturedOuterClassDescriptor + if (captureThis != null) { + val type = typeMapper.mapType(captureThis) val descriptor = EnclosedValueDescriptor( AsmUtil.CAPTURED_THIS_FIELD, null, StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0), @@ -261,8 +262,8 @@ class PsiExpressionLambda( add(getCapturedParamInfo(descriptor)) } - if (closure.captureReceiverType != null) { - val type = typeMapper.mapType(closure.captureReceiverType!!).let { + if (closure.capturedReceiverFromOuterContext != null) { + val type = typeMapper.mapType(closure.capturedReceiverFromOuterContext!!).let { if (isBoundCallableReference) it.boxReceiverForBoundReference() else it } val descriptor = EnclosedValueDescriptor( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index e1a2f2dadf5..1e3b996fe70 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -1573,7 +1573,7 @@ public class KotlinTypeMapper { writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor); } - KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null; + KotlinType captureReceiverType = closure != null ? closure.getCapturedReceiverFromOuterContext() : null; if (captureReceiverType != null) { writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType, descriptor); }