Rename receiver$0 in CallableReference to receiver

#KT-15449 Fixed
This commit is contained in:
Mikhael Bogdanov
2016-12-28 14:21:00 +01:00
parent 4774d19890
commit 2566a7a25e
17 changed files with 96 additions and 29 deletions
@@ -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,
@@ -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");
@@ -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
@@ -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");