Rename receiver$0 in CallableReference to receiver
#KT-15449 Fixed
This commit is contained in:
@@ -95,6 +95,7 @@ public class AsmUtil {
|
||||
.put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
|
||||
.build();
|
||||
|
||||
public static final String BOUND_REFERENCE_RECEIVER = "receiver";
|
||||
public static final String RECEIVER_NAME = "$receiver";
|
||||
public static final String CAPTURED_RECEIVER_FIELD = "receiver$0";
|
||||
public static final String CAPTURED_THIS_FIELD = "this$0";
|
||||
|
||||
@@ -91,7 +91,6 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
|
||||
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
@@ -3269,7 +3268,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||
if (functionDescriptor != null) {
|
||||
FunctionReferenceGenerationStrategy strategy =
|
||||
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null);
|
||||
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null, false);
|
||||
|
||||
return genClosure(
|
||||
expression, functionDescriptor, strategy, null,
|
||||
|
||||
+5
-2
@@ -42,13 +42,15 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
private final Type receiverType; // non-null for bound references
|
||||
private final StackValue receiverValue;
|
||||
private final boolean isInliningStrategy;
|
||||
|
||||
public FunctionReferenceGenerationStrategy(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@Nullable Type receiverType,
|
||||
@Nullable StackValue receiverValue
|
||||
@Nullable StackValue receiverValue,
|
||||
boolean isInliningStrategy
|
||||
) {
|
||||
super(state);
|
||||
this.resolvedCall = resolvedCall;
|
||||
@@ -56,6 +58,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
this.receiverType = receiverType;
|
||||
this.receiverValue = receiverValue;
|
||||
this.isInliningStrategy = isInliningStrategy;
|
||||
assert receiverType != null || receiverValue == null
|
||||
: "A receiver value is provided for unbound function reference. Either this is a bound reference and you forgot " +
|
||||
"to pass receiverType, or you accidentally passed some receiverValue for a reference without receiver";
|
||||
@@ -187,7 +190,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
if (receiverType != null) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
||||
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
|
||||
return CallableReferenceUtilKt.capturedBoundReferenceReceiver(asmType, receiverType);
|
||||
return CallableReferenceUtilKt.capturedBoundReferenceReceiver(asmType, receiverType, isInliningStrategy);
|
||||
}
|
||||
|
||||
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
||||
|
||||
@@ -146,12 +146,12 @@ class PropertyReferenceCodegen(
|
||||
private fun generateAccessors() {
|
||||
val getFunction = findGetFunction(localVariableDescriptorForReference)
|
||||
val getImpl = createFakeOpenDescriptor(getFunction, classDescriptor)
|
||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, getImpl, PropertyReferenceGenerationStrategy(true, getFunction, target, asmType, receiverType, element, state))
|
||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, getImpl, PropertyReferenceGenerationStrategy(true, getFunction, target, asmType, receiverType, element, state, false))
|
||||
|
||||
if (!ReflectionTypes.isNumberedKMutablePropertyType(localVariableDescriptorForReference.type)) return
|
||||
val setFunction = localVariableDescriptorForReference.type.memberScope.getContributedFunctions(OperatorNameConventions.SET, NoLookupLocation.FROM_BACKEND).single()
|
||||
val setImpl = createFakeOpenDescriptor(setFunction, classDescriptor)
|
||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, setImpl, PropertyReferenceGenerationStrategy(false, setFunction, target, asmType, receiverType, element, state))
|
||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, setImpl, PropertyReferenceGenerationStrategy(false, setFunction, target, asmType, receiverType, element, state, false))
|
||||
}
|
||||
|
||||
|
||||
@@ -243,7 +243,8 @@ class PropertyReferenceCodegen(
|
||||
val asmType: Type,
|
||||
val receiverType: Type?,
|
||||
val expression: KtElement,
|
||||
state: GenerationState
|
||||
state: GenerationState,
|
||||
val isInliningStrategy: Boolean
|
||||
) :
|
||||
FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
@@ -258,7 +259,7 @@ class PropertyReferenceCodegen(
|
||||
val expectedReceiver = target.dispatchReceiverParameter ?: target.extensionReceiverParameter ?:
|
||||
throw AssertionError("receiverType: $receiverType; no dispatch or extension receiver: $target")
|
||||
val expectedReceiverType = typeMapper.mapType(expectedReceiver.type)
|
||||
capturedBoundReferenceReceiver(asmType, expectedReceiverType).put(expectedReceiverType, v)
|
||||
capturedBoundReferenceReceiver(asmType, expectedReceiverType, isInliningStrategy).put(expectedReceiverType, v)
|
||||
}
|
||||
else {
|
||||
val receivers = originalFunctionDesc.valueParameters.dropLast(if (isGetter) 0 else 1)
|
||||
|
||||
@@ -24,10 +24,15 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type): StackValue =
|
||||
fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type, isInliningStrategy: Boolean): StackValue =
|
||||
StackValue.operation(expectedReceiverType) { iv ->
|
||||
iv.load(0, ownerType)
|
||||
iv.getfield(ownerType.internalName, AsmUtil.CAPTURED_RECEIVER_FIELD, AsmTypes.OBJECT_TYPE.descriptor)
|
||||
iv.getfield(
|
||||
ownerType.internalName,
|
||||
//HACK for inliner - it should recognize field as captured receiver
|
||||
if (isInliningStrategy) AsmUtil.CAPTURED_RECEIVER_FIELD else AsmUtil.BOUND_REFERENCE_RECEIVER,
|
||||
AsmTypes.OBJECT_TYPE.descriptor
|
||||
)
|
||||
StackValue.coerce(AsmTypes.OBJECT_TYPE, expectedReceiverType, iv)
|
||||
}
|
||||
|
||||
|
||||
@@ -581,8 +581,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
|
||||
PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
|
||||
strategy = new PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
||||
true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state
|
||||
);
|
||||
true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state, true);
|
||||
}
|
||||
else {
|
||||
strategy = new FunctionReferenceGenerationStrategy(
|
||||
@@ -591,7 +590,8 @@ public class InlineCodegen extends CallGenerator {
|
||||
CallUtilKt
|
||||
.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
||||
receiverType,
|
||||
null
|
||||
null,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// FILE: 1.kt
|
||||
|
||||
package test
|
||||
|
||||
inline fun linearLayout2(init: X.() -> Unit) {
|
||||
return X().init()
|
||||
}
|
||||
|
||||
var result = "fail"
|
||||
class X {
|
||||
fun calc() {
|
||||
result = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
//NO_CHECK_LAMBDA_INLINING
|
||||
import test.*
|
||||
|
||||
class A {
|
||||
fun test() {
|
||||
linearLayout2 {
|
||||
{
|
||||
apply2 {
|
||||
this@linearLayout2::calc
|
||||
}()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T, Z> T.apply2(block: T.() -> Z): Z {
|
||||
return block()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
A().test()
|
||||
return result
|
||||
}
|
||||
@@ -584,6 +584,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt15449.kt")
|
||||
public void testKt15449() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/kt15449.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyIntrinsic.kt")
|
||||
public void testPropertyIntrinsic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||
|
||||
+6
@@ -584,6 +584,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt15449.kt")
|
||||
public void testKt15449() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/kt15449.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyIntrinsic.kt")
|
||||
public void testPropertyIntrinsic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||
|
||||
@@ -39,21 +39,21 @@ public abstract class CallableReference implements KCallable {
|
||||
// objects are written to it. The latter is guaranteed because both KFunctionImpl and KPropertyImpl have at least one final field.
|
||||
private KCallable reflected;
|
||||
|
||||
protected final Object receiver$0;
|
||||
protected final Object receiver;
|
||||
public static final Object NO_RECEIVER = new Object();
|
||||
|
||||
public CallableReference() {
|
||||
this(NO_RECEIVER);
|
||||
}
|
||||
|
||||
protected CallableReference(Object receiver$0) {
|
||||
this.receiver$0 = receiver$0;
|
||||
protected CallableReference(Object receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
protected abstract KCallable computeReflected();
|
||||
|
||||
public Object getBoundReceiver() {
|
||||
return receiver$0;
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public KCallable compute() {
|
||||
|
||||
@@ -22,7 +22,7 @@ public abstract class MutablePropertyReference extends PropertyReference impleme
|
||||
public MutablePropertyReference() {
|
||||
}
|
||||
|
||||
public MutablePropertyReference(Object receiver$0) {
|
||||
super(receiver$0);
|
||||
public MutablePropertyReference(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ public abstract class MutablePropertyReference0 extends MutablePropertyReference
|
||||
public MutablePropertyReference0() {
|
||||
}
|
||||
|
||||
public MutablePropertyReference0(Object receiver$0) {
|
||||
super(receiver$0);
|
||||
public MutablePropertyReference0(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,8 @@ public abstract class MutablePropertyReference1 extends MutablePropertyReference
|
||||
public MutablePropertyReference1() {
|
||||
}
|
||||
|
||||
public MutablePropertyReference1(Object receiver$0) {
|
||||
super(receiver$0);
|
||||
public MutablePropertyReference1(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,8 @@ public abstract class PropertyReference extends CallableReference implements KPr
|
||||
super();
|
||||
}
|
||||
|
||||
public PropertyReference(Object receiver$0) {
|
||||
super(receiver$0);
|
||||
public PropertyReference(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,8 @@ public abstract class PropertyReference0 extends PropertyReference implements KP
|
||||
super();
|
||||
}
|
||||
|
||||
public PropertyReference0(Object receiver$0) {
|
||||
super(receiver$0);
|
||||
public PropertyReference0(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,8 +23,8 @@ public abstract class PropertyReference1 extends PropertyReference implements KP
|
||||
public PropertyReference1() {
|
||||
}
|
||||
|
||||
public PropertyReference1(Object receiver$0) {
|
||||
super(receiver$0);
|
||||
public PropertyReference1(Object receiver) {
|
||||
super(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
@@ -78,6 +78,12 @@ public class CallableReferenceInlineTestsGenerated extends AbstractCallableRefer
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("kt15449.kt")
|
||||
public void testKt15449() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/kt15449.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyIntrinsic.kt")
|
||||
public void testPropertyIntrinsic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||
|
||||
Reference in New Issue
Block a user