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)
|
.put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static final String BOUND_REFERENCE_RECEIVER = "receiver";
|
||||||
public static final String RECEIVER_NAME = "$receiver";
|
public static final String RECEIVER_NAME = "$receiver";
|
||||||
public static final String CAPTURED_RECEIVER_FIELD = "receiver$0";
|
public static final String CAPTURED_RECEIVER_FIELD = "receiver$0";
|
||||||
public static final String CAPTURED_THIS_FIELD = "this$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.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeProjection;
|
import org.jetbrains.kotlin.types.TypeProjection;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
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.expressions.DoubleColonLHS;
|
||||||
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||||
@@ -3269,7 +3268,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
FunctionReferenceGenerationStrategy strategy =
|
FunctionReferenceGenerationStrategy strategy =
|
||||||
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null);
|
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null, false);
|
||||||
|
|
||||||
return genClosure(
|
return genClosure(
|
||||||
expression, functionDescriptor, strategy, null,
|
expression, functionDescriptor, strategy, null,
|
||||||
|
|||||||
+5
-2
@@ -42,13 +42,15 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
|||||||
private final FunctionDescriptor functionDescriptor;
|
private final FunctionDescriptor functionDescriptor;
|
||||||
private final Type receiverType; // non-null for bound references
|
private final Type receiverType; // non-null for bound references
|
||||||
private final StackValue receiverValue;
|
private final StackValue receiverValue;
|
||||||
|
private final boolean isInliningStrategy;
|
||||||
|
|
||||||
public FunctionReferenceGenerationStrategy(
|
public FunctionReferenceGenerationStrategy(
|
||||||
@NotNull GenerationState state,
|
@NotNull GenerationState state,
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
@NotNull ResolvedCall<?> resolvedCall,
|
@NotNull ResolvedCall<?> resolvedCall,
|
||||||
@Nullable Type receiverType,
|
@Nullable Type receiverType,
|
||||||
@Nullable StackValue receiverValue
|
@Nullable StackValue receiverValue,
|
||||||
|
boolean isInliningStrategy
|
||||||
) {
|
) {
|
||||||
super(state);
|
super(state);
|
||||||
this.resolvedCall = resolvedCall;
|
this.resolvedCall = resolvedCall;
|
||||||
@@ -56,6 +58,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
|||||||
this.functionDescriptor = functionDescriptor;
|
this.functionDescriptor = functionDescriptor;
|
||||||
this.receiverType = receiverType;
|
this.receiverType = receiverType;
|
||||||
this.receiverValue = receiverValue;
|
this.receiverValue = receiverValue;
|
||||||
|
this.isInliningStrategy = isInliningStrategy;
|
||||||
assert receiverType != null || receiverValue == null
|
assert receiverType != null || receiverValue == null
|
||||||
: "A receiver value is provided for unbound function reference. Either this is a bound reference and you forgot " +
|
: "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";
|
"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) {
|
if (receiverType != null) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
||||||
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
|
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
|
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
||||||
|
|||||||
@@ -146,12 +146,12 @@ class PropertyReferenceCodegen(
|
|||||||
private fun generateAccessors() {
|
private fun generateAccessors() {
|
||||||
val getFunction = findGetFunction(localVariableDescriptorForReference)
|
val getFunction = findGetFunction(localVariableDescriptorForReference)
|
||||||
val getImpl = createFakeOpenDescriptor(getFunction, classDescriptor)
|
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
|
if (!ReflectionTypes.isNumberedKMutablePropertyType(localVariableDescriptorForReference.type)) return
|
||||||
val setFunction = localVariableDescriptorForReference.type.memberScope.getContributedFunctions(OperatorNameConventions.SET, NoLookupLocation.FROM_BACKEND).single()
|
val setFunction = localVariableDescriptorForReference.type.memberScope.getContributedFunctions(OperatorNameConventions.SET, NoLookupLocation.FROM_BACKEND).single()
|
||||||
val setImpl = createFakeOpenDescriptor(setFunction, classDescriptor)
|
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 asmType: Type,
|
||||||
val receiverType: Type?,
|
val receiverType: Type?,
|
||||||
val expression: KtElement,
|
val expression: KtElement,
|
||||||
state: GenerationState
|
state: GenerationState,
|
||||||
|
val isInliningStrategy: Boolean
|
||||||
) :
|
) :
|
||||||
FunctionGenerationStrategy.CodegenBased(state) {
|
FunctionGenerationStrategy.CodegenBased(state) {
|
||||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||||
@@ -258,7 +259,7 @@ class PropertyReferenceCodegen(
|
|||||||
val expectedReceiver = target.dispatchReceiverParameter ?: target.extensionReceiverParameter ?:
|
val expectedReceiver = target.dispatchReceiverParameter ?: target.extensionReceiverParameter ?:
|
||||||
throw AssertionError("receiverType: $receiverType; no dispatch or extension receiver: $target")
|
throw AssertionError("receiverType: $receiverType; no dispatch or extension receiver: $target")
|
||||||
val expectedReceiverType = typeMapper.mapType(expectedReceiver.type)
|
val expectedReceiverType = typeMapper.mapType(expectedReceiver.type)
|
||||||
capturedBoundReferenceReceiver(asmType, expectedReceiverType).put(expectedReceiverType, v)
|
capturedBoundReferenceReceiver(asmType, expectedReceiverType, isInliningStrategy).put(expectedReceiverType, v)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val receivers = originalFunctionDesc.valueParameters.dropLast(if (isGetter) 0 else 1)
|
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.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
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 ->
|
StackValue.operation(expectedReceiverType) { iv ->
|
||||||
iv.load(0, ownerType)
|
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)
|
StackValue.coerce(AsmTypes.OBJECT_TYPE, expectedReceiverType, iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -581,8 +581,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
|
Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
|
||||||
PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
|
PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
|
||||||
strategy = new PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
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 {
|
else {
|
||||||
strategy = new FunctionReferenceGenerationStrategy(
|
strategy = new FunctionReferenceGenerationStrategy(
|
||||||
@@ -591,7 +590,8 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
CallUtilKt
|
CallUtilKt
|
||||||
.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
||||||
receiverType,
|
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);
|
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")
|
@TestMetadata("propertyIntrinsic.kt")
|
||||||
public void testPropertyIntrinsic() throws Exception {
|
public void testPropertyIntrinsic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||||
|
|||||||
+6
@@ -584,6 +584,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("propertyIntrinsic.kt")
|
||||||
public void testPropertyIntrinsic() throws Exception {
|
public void testPropertyIntrinsic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
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.
|
// objects are written to it. The latter is guaranteed because both KFunctionImpl and KPropertyImpl have at least one final field.
|
||||||
private KCallable reflected;
|
private KCallable reflected;
|
||||||
|
|
||||||
protected final Object receiver$0;
|
protected final Object receiver;
|
||||||
public static final Object NO_RECEIVER = new Object();
|
public static final Object NO_RECEIVER = new Object();
|
||||||
|
|
||||||
public CallableReference() {
|
public CallableReference() {
|
||||||
this(NO_RECEIVER);
|
this(NO_RECEIVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CallableReference(Object receiver$0) {
|
protected CallableReference(Object receiver) {
|
||||||
this.receiver$0 = receiver$0;
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract KCallable computeReflected();
|
protected abstract KCallable computeReflected();
|
||||||
|
|
||||||
public Object getBoundReceiver() {
|
public Object getBoundReceiver() {
|
||||||
return receiver$0;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KCallable compute() {
|
public KCallable compute() {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public abstract class MutablePropertyReference extends PropertyReference impleme
|
|||||||
public MutablePropertyReference() {
|
public MutablePropertyReference() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutablePropertyReference(Object receiver$0) {
|
public MutablePropertyReference(Object receiver) {
|
||||||
super(receiver$0);
|
super(receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public abstract class MutablePropertyReference0 extends MutablePropertyReference
|
|||||||
public MutablePropertyReference0() {
|
public MutablePropertyReference0() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutablePropertyReference0(Object receiver$0) {
|
public MutablePropertyReference0(Object receiver) {
|
||||||
super(receiver$0);
|
super(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public abstract class MutablePropertyReference1 extends MutablePropertyReference
|
|||||||
public MutablePropertyReference1() {
|
public MutablePropertyReference1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutablePropertyReference1(Object receiver$0) {
|
public MutablePropertyReference1(Object receiver) {
|
||||||
super(receiver$0);
|
super(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public abstract class PropertyReference extends CallableReference implements KPr
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyReference(Object receiver$0) {
|
public PropertyReference(Object receiver) {
|
||||||
super(receiver$0);
|
super(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public abstract class PropertyReference0 extends PropertyReference implements KP
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyReference0(Object receiver$0) {
|
public PropertyReference0(Object receiver) {
|
||||||
super(receiver$0);
|
super(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public abstract class PropertyReference1 extends PropertyReference implements KP
|
|||||||
public PropertyReference1() {
|
public PropertyReference1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyReference1(Object receiver$0) {
|
public PropertyReference1(Object receiver) {
|
||||||
super(receiver$0);
|
super(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.");
|
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")
|
@TestMetadata("propertyIntrinsic.kt")
|
||||||
public void testPropertyIntrinsic() throws Exception {
|
public void testPropertyIntrinsic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user