Introduce AdaptedFunctionReference runtime class

It's used as a superclass for anonymous classes for adapted function
references. Its main feature is that it _doesn't_ inherit from KFunction
(as opposed to FunctionReference), as per the decision to postpone
reflection support for adapted function references in KT-36024.

 #KT-36024 Fixed
This commit is contained in:
Alexander Udalov
2020-04-03 21:14:00 +02:00
parent d1c5a42124
commit 0681231e99
14 changed files with 178 additions and 85 deletions
@@ -74,7 +74,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
protected final Type asmType; protected final Type asmType;
protected final int visibilityFlag; protected final int visibilityFlag;
private final boolean shouldHaveBoundReferenceReceiver; private final boolean shouldHaveBoundReferenceReceiver;
private final boolean isRegularFunctionReference; private final boolean isLegacyFunctionReference;
private final boolean isOptimizedFunctionReference; private final boolean isOptimizedFunctionReference;
private final boolean isAdaptedFunctionReference; private final boolean isAdaptedFunctionReference;
@@ -129,7 +129,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
this.shouldHaveBoundReferenceReceiver = CallableReferenceUtilKt.isForBoundCallableReference(closure); this.shouldHaveBoundReferenceReceiver = CallableReferenceUtilKt.isForBoundCallableReference(closure);
ClassifierDescriptor superClassDescriptor = superClassType.getConstructor().getDeclarationDescriptor(); ClassifierDescriptor superClassDescriptor = superClassType.getConstructor().getDeclarationDescriptor();
this.isRegularFunctionReference = this.isLegacyFunctionReference =
functionReferenceTarget != null && functionReferenceTarget != null &&
superClassDescriptor == state.getJvmRuntimeTypes().getFunctionReference(); superClassDescriptor == state.getJvmRuntimeTypes().getFunctionReference();
this.isOptimizedFunctionReference = this.isOptimizedFunctionReference =
@@ -137,7 +137,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
superClassDescriptor == state.getJvmRuntimeTypes().getFunctionReferenceImpl(); superClassDescriptor == state.getJvmRuntimeTypes().getFunctionReferenceImpl();
this.isAdaptedFunctionReference = this.isAdaptedFunctionReference =
functionReferenceTarget != null && functionReferenceTarget != null &&
superClassDescriptor == state.getJvmRuntimeTypes().getLambda(); superClassDescriptor == state.getJvmRuntimeTypes().getAdaptedFunctionReference();
this.asmType = typeMapper.mapClass(classDescriptor); this.asmType = typeMapper.mapClass(classDescriptor);
@@ -199,29 +199,15 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
protected void generateClosureBody() { protected void generateClosureBody() {
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), funDescriptor, strategy); functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), funDescriptor, strategy);
if (isRegularFunctionReference) { if (isLegacyFunctionReference) {
generateFunctionReferenceMethods(functionReferenceTarget); generateFunctionReferenceMethods(functionReferenceTarget);
} }
if (shouldHaveBoundReferenceReceiver && isAdaptedFunctionReference) {
generateBoundAdaptedCallableReferenceReceiverField();
}
functionCodegen.generateDefaultIfNeeded( functionCodegen.generateDefaultIfNeeded(
context.intoFunction(funDescriptor), funDescriptor, context.getContextKind(), DefaultParameterValueLoader.DEFAULT, null context.intoFunction(funDescriptor), funDescriptor, context.getContextKind(), DefaultParameterValueLoader.DEFAULT, null
); );
} }
private void generateBoundAdaptedCallableReferenceReceiverField() {
v.newField(
JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor),
ACC_PRIVATE,
BOUND_REFERENCE_RECEIVER,
OBJECT_TYPE.getDescriptor(),
null, null
);
}
protected void generateBridges() { protected void generateBridges() {
FunctionDescriptor erasedInterfaceFunction; FunctionDescriptor erasedInterfaceFunction;
if (samType == null) { if (samType == null) {
@@ -522,20 +508,19 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
iv.load(0, superClassAsmType); iv.load(0, superClassAsmType);
List<Type> superCtorArgTypes = new ArrayList<>(); List<Type> superCtorArgTypes = new ArrayList<>();
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) || if (superClassAsmType.equals(LAMBDA) || functionReferenceTarget != null ||
superClassAsmType.equals(FUNCTION_REFERENCE_IMPL) ||
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName()) CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())
) { ) {
int arity = calculateArity(); int arity = calculateArity();
iv.iconst(arity); iv.iconst(arity);
superCtorArgTypes.add(Type.INT_TYPE); superCtorArgTypes.add(Type.INT_TYPE);
if (shouldHaveBoundReferenceReceiver && !isAdaptedFunctionReference) { if (shouldHaveBoundReferenceReceiver) {
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter( CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(
iv, boundReceiverParameterIndex, boundReceiverType, boundReceiverKotlinType iv, boundReceiverParameterIndex, boundReceiverType, boundReceiverKotlinType
); );
superCtorArgTypes.add(OBJECT_TYPE); superCtorArgTypes.add(OBJECT_TYPE);
} }
if (isOptimizedFunctionReference) { if (isOptimizedFunctionReference || isAdaptedFunctionReference) {
assert functionReferenceTarget != null : "No function reference target: " + funDescriptor; assert functionReferenceTarget != null : "No function reference target: " + funDescriptor;
generateCallableReferenceDeclarationContainerClass(iv, functionReferenceTarget, state); generateCallableReferenceDeclarationContainerClass(iv, functionReferenceTarget, state);
iv.aconst(functionReferenceTarget.getName().asString()); iv.aconst(functionReferenceTarget.getName().asString());
@@ -558,19 +543,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
Type.getMethodDescriptor(Type.VOID_TYPE, superCtorArgTypes.toArray(new Type[0])), false Type.getMethodDescriptor(Type.VOID_TYPE, superCtorArgTypes.toArray(new Type[0])), false
); );
// Bound adapted function references store receiver in a separate field.
if (shouldHaveBoundReferenceReceiver && isAdaptedFunctionReference) {
iv.load(0, superClassAsmType);
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(
iv, boundReceiverParameterIndex, boundReceiverType, boundReceiverKotlinType
);
iv.putfield(
asmType.getInternalName(),
BOUND_REFERENCE_RECEIVER,
OBJECT_TYPE.getDescriptor()
);
}
iv.visitInsn(RETURN); iv.visitInsn(RETURN);
FunctionCodegen.endVisit(iv, "constructor", element); FunctionCodegen.endVisit(iv, "constructor", element);
@@ -43,9 +43,10 @@ class JvmRuntimeTypes(
private fun propertyClasses(prefix: String, suffix: String): Lazy<List<ClassDescriptor>> = private fun propertyClasses(prefix: String, suffix: String): Lazy<List<ClassDescriptor>> =
lazy { (0..2).map { i -> createClass(kotlinJvmInternalPackage, prefix + i + suffix) } } lazy { (0..2).map { i -> createClass(kotlinJvmInternalPackage, prefix + i + suffix) } }
val lambda: ClassDescriptor by internal("Lambda") private val lambda: ClassDescriptor by internal("Lambda")
val functionReference: ClassDescriptor by internal("FunctionReference") val functionReference: ClassDescriptor by internal("FunctionReference")
val functionReferenceImpl: ClassDescriptor by internal("FunctionReferenceImpl") val functionReferenceImpl: ClassDescriptor by internal("FunctionReferenceImpl")
val adaptedFunctionReference: ClassDescriptor by internal("AdaptedFunctionReference")
private val localVariableReference: ClassDescriptor by internal("LocalVariableReference") private val localVariableReference: ClassDescriptor by internal("LocalVariableReference")
private val mutableLocalVariableReference: ClassDescriptor by internal("MutableLocalVariableReference") private val mutableLocalVariableReference: ClassDescriptor by internal("MutableLocalVariableReference")
@@ -152,7 +153,7 @@ class JvmRuntimeTypes(
val suspendFunctionType = if (referencedFunction.isSuspend) suspendFunctionInterface?.defaultType else null val suspendFunctionType = if (referencedFunction.isSuspend) suspendFunctionInterface?.defaultType else null
val superClass = when { val superClass = when {
isAdaptedCallableReference -> lambda isAdaptedCallableReference -> adaptedFunctionReference
generateOptimizedCallableReferenceSuperClasses -> functionReferenceImpl generateOptimizedCallableReferenceSuperClasses -> functionReferenceImpl
else -> functionReference else -> functionReference
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
@@ -314,21 +315,33 @@ class JvmSymbols(
klass.superTypes = listOf(functionReference.defaultType) klass.superTypes = listOf(functionReference.defaultType)
if (generateOptimizedCallableReferenceSuperClasses) { if (generateOptimizedCallableReferenceSuperClasses) {
for (hasBoundReceiver in listOf(false, true)) { klass.generateCallableReferenceSuperclassConstructors(withArity = true)
klass.addConstructor().apply {
addValueParameter("arity", irBuiltIns.intType)
if (hasBoundReceiver) {
addValueParameter("receiver", irBuiltIns.anyNType)
}
addValueParameter("owner", javaLangClass.starProjectedType)
addValueParameter("name", irBuiltIns.stringType)
addValueParameter("signature", irBuiltIns.stringType)
addValueParameter("flags", irBuiltIns.intType)
}
}
} }
} }
val adaptedFunctionReference: IrClassSymbol =
createClass(FqName("kotlin.jvm.internal.AdaptedFunctionReference"), classModality = Modality.OPEN) { klass ->
klass.superTypes = listOf(irBuiltIns.anyType)
klass.generateCallableReferenceSuperclassConstructors(withArity = true)
}
private fun IrClass.generateCallableReferenceSuperclassConstructors(withArity: Boolean) {
for (hasBoundReceiver in listOf(false, true)) {
addConstructor().apply {
if (withArity) {
addValueParameter("arity", irBuiltIns.intType)
}
if (hasBoundReceiver) {
addValueParameter("receiver", irBuiltIns.anyNType)
}
addValueParameter("owner", javaLangClass.starProjectedType)
addValueParameter("name", irBuiltIns.stringType)
addValueParameter("signature", irBuiltIns.stringType)
addValueParameter("flags", irBuiltIns.intType)
}
}
}
fun getFunction(parameterCount: Int): IrClassSymbol = fun getFunction(parameterCount: Int): IrClassSymbol =
symbolTable.referenceClass(builtIns.getFunction(parameterCount)) symbolTable.referenceClass(builtIns.getFunction(parameterCount))
@@ -403,17 +416,7 @@ class JvmSymbols(
} }
if (generateOptimizedCallableReferenceSuperClasses) { if (generateOptimizedCallableReferenceSuperClasses) {
for (hasBoundReceiver in listOf(false, true)) { klass.generateCallableReferenceSuperclassConstructors(withArity = false)
klass.addConstructor().apply {
if (hasBoundReceiver) {
addValueParameter("receiver", irBuiltIns.anyNType)
}
addValueParameter("owner", javaLangClass.starProjectedType)
addValueParameter("name", irBuiltIns.stringType)
addValueParameter("signature", irBuiltIns.stringType)
addValueParameter("flags", irBuiltIns.intType)
}
}
} }
klass.superTypes += getPropertyReferenceClass(mutable, parameterCount, false).defaultType klass.superTypes += getPropertyReferenceClass(mutable, parameterCount, false).defaultType
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -119,10 +120,32 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
context.ir.symbols.getJvmFunctionClass(argumentTypes.size) context.ir.symbols.getJvmFunctionClass(argumentTypes.size)
private val superMethod = private val superMethod =
functionSuperClass.functions.single { it.owner.modality == Modality.ABSTRACT } functionSuperClass.functions.single { it.owner.modality == Modality.ABSTRACT }
private val useOptimizedSuperClass = private val useOptimizedSuperClass =
context.state.generateOptimizedCallableReferenceSuperClasses context.state.generateOptimizedCallableReferenceSuperClasses
private val adaptedReferenceOriginalTarget = if (callee.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) {
// The body of a callable reference adapter contains either only a call, or an IMPLICIT_COERCION_TO_UNIT type operator
// applied to a call. That call's target is the original function which we need to get owner/name/signature.
val call = when (val statement = callee.body!!.statements.single()) {
is IrTypeOperatorCall -> {
assert(statement.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) {
"Unexpected type operator in ADAPTER_FOR_CALLABLE_REFERENCE: ${callee.render()}"
}
statement.argument
}
is IrReturn -> statement.value
else -> statement
}
if (call !is IrFunctionAccessExpression) {
throw UnsupportedOperationException("Unknown structure of ADAPTER_FOR_CALLABLE_REFERENCE: ${callee.render()}")
}
call.symbol.owner
} else null
private val superType = private val superType =
samSuperType ?: when { samSuperType ?: when {
adaptedReferenceOriginalTarget != null -> context.ir.symbols.adaptedFunctionReference
isLambda -> context.ir.symbols.lambdaClass isLambda -> context.ir.symbols.lambdaClass
useOptimizedSuperClass -> context.ir.symbols.functionReferenceImpl useOptimizedSuperClass -> context.ir.symbols.functionReferenceImpl
else -> context.ir.symbols.functionReference else -> context.ir.symbols.functionReference
@@ -171,7 +194,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
if (!isLambda && samSuperType == null && !useOptimizedSuperClass) { if (!isLambda && samSuperType == null && !useOptimizedSuperClass) {
createLegacyMethodOverride(irSymbols.functionReferenceGetSignature.owner) { createLegacyMethodOverride(irSymbols.functionReferenceGetSignature.owner) {
generateSignature() generateSignature(callee.symbol)
} }
createLegacyMethodOverride(irSymbols.functionReferenceGetName.owner) { createLegacyMethodOverride(irSymbols.functionReferenceGetName.owner) {
irString(callee.originalName.asString()) irString(callee.originalName.asString())
@@ -215,9 +238,11 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
val constructor = if (samSuperType != null) { val constructor = if (samSuperType != null) {
context.irBuiltIns.anyClass.owner.constructors.single() context.irBuiltIns.anyClass.owner.constructors.single()
} else { } else {
val expectedArity = val expectedArity = when {
if (isLambda) 1 adaptedReferenceOriginalTarget != null -> 5 + (if (boundReceiver != null) 1 else 0)
else 1 + (if (boundReceiver != null) 1 else 0) + (if (useOptimizedSuperClass) 4 else 0) isLambda -> 1
else -> 1 + (if (boundReceiver != null) 1 else 0) + (if (useOptimizedSuperClass) 4 else 0)
}
superType.getClass()!!.constructors.single { superType.getClass()!!.constructors.single {
it.valueParameters.size == expectedArity it.valueParameters.size == expectedArity
} }
@@ -232,13 +257,20 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
if (boundReceiver != null) { if (boundReceiver != null) {
putValueArgument(index++, irGet(valueParameters.first())) putValueArgument(index++, irGet(valueParameters.first()))
} }
if (!isLambda && useOptimizedSuperClass) { val callableReferenceTarget = when {
val owner = calculateOwnerKClass(callee.parent, backendContext) adaptedReferenceOriginalTarget != null -> adaptedReferenceOriginalTarget
!isLambda && useOptimizedSuperClass -> callee
else -> null
}
if (callableReferenceTarget != null) {
val owner = calculateOwnerKClass(callableReferenceTarget.parent, backendContext)
putValueArgument(index++, kClassToJavaClass(owner, backendContext)) putValueArgument(index++, kClassToJavaClass(owner, backendContext))
putValueArgument(index++, irString(callee.originalName.asString())) putValueArgument(index++, irString(callableReferenceTarget.originalName.asString()))
putValueArgument(index++, generateSignature()) putValueArgument(index++, generateSignature(callableReferenceTarget.symbol))
// TODO: use correct parents for adapted function references putValueArgument(
putValueArgument(index, irInt(if (callee.parent.let { it is IrClass && it.isFileClass }) 1 else 0)) index,
irInt(if (callableReferenceTarget.parent.let { it is IrClass && it.isFileClass }) 1 else 0)
)
} }
} }
} }
@@ -346,14 +378,13 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
private val IrFunction.originalName: Name private val IrFunction.originalName: Name
get() = (metadata as? MetadataSource.Function)?.descriptor?.name ?: name get() = (metadata as? MetadataSource.Function)?.descriptor?.name ?: name
private fun JvmIrBuilder.generateSignature(): IrExpression = private fun JvmIrBuilder.generateSignature(target: IrFunctionSymbol): IrExpression =
irCall(backendContext.ir.symbols.signatureStringIntrinsic).apply { irCall(backendContext.ir.symbols.signatureStringIntrinsic).apply {
putValueArgument( putValueArgument(
0, 0,
//don't pass receivers otherwise LocalDeclarationLowering will create additional captured parameters //don't pass receivers otherwise LocalDeclarationLowering will create additional captured parameters
IrFunctionReferenceImpl( IrFunctionReferenceImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunctionReference.type, irFunctionReference.symbol, 0, UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunctionReference.type, target, 0, irFunctionReference.reflectionTarget, null
irFunctionReference.reflectionTarget, null
) )
) )
} }
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR, JS, JS_IR, NATIVE // IGNORE_BACKEND: JS, JS_IR, NATIVE
// FILE: test.kt // FILE: test.kt
fun checkEqual(x: Any, y: Any) { fun checkEqual(x: Any, y: Any) {
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR, JS, JS_IR, NATIVE // IGNORE_BACKEND: JS, JS_IR, NATIVE
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt // FILE: test.kt
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR, JS, JS_IR, NATIVE // IGNORE_BACKEND: JS, JS_IR, NATIVE
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt // FILE: test.kt
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR, JS, JS_IR, NATIVE // IGNORE_BACKEND: JS, JS_IR, NATIVE
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt // FILE: test.kt
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR, JS, JS_IR, NATIVE // IGNORE_BACKEND: JS, JS_IR, NATIVE
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt // FILE: test.kt
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR, JS, JS_IR, NATIVE // IGNORE_BACKEND: JS, JS_IR, NATIVE
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// FILE: test.kt // FILE: test.kt
@@ -30,9 +30,8 @@ fun box(): String {
checkAny("::CWithDefaults", ::CWithDefaults) checkAny("::CWithDefaults", ::CWithDefaults)
checkAny("::CWithVarargs", ::CWithVarargs) checkAny("::CWithVarargs", ::CWithVarargs)
// TODO KT-37604 checkUnit("::CWithDefaults", ::CWithDefaults)
// checkUnit("::CWithDefaults", ::CWithDefaults) checkUnit("::CWithVarargs", ::CWithVarargs)
// checkUnit("::CWithVarargs", ::CWithVarargs)
return "OK" return "OK"
} }
@@ -1,6 +1,4 @@
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// Temporarily ignored for JVM until KT-36024 is fixed.
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT // WITH_REFLECT
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package kotlin.jvm.internal;
import kotlin.SinceKotlin;
import kotlin.reflect.KDeclarationContainer;
import static kotlin.jvm.internal.CallableReference.NO_RECEIVER;
/**
* Superclass for instances of adapted function references, i.e. references where expected function type differs
* from the target function signature: <pre>
* fun target(s: String? = ""): String = s!!
* fun use(f: () -> Unit) {}
* use(::target) // adapted function reference (default argument conversion + coercion to Unit)
* </pre>
*
* It doesn't inherit from {@link FunctionReference} because such references don't support reflection yet.
* Once this changes in the future, the JVM codegen may simply use {@link FunctionReferenceImpl}
* for adapted function references instead of this class.
*/
@SuppressWarnings({"rawtypes", "WeakerAccess", "unused"})
@SinceKotlin(version = "1.4")
public class AdaptedFunctionReference {
protected final Object receiver;
private final Class owner;
private final String name;
private final String signature;
private final boolean isTopLevel;
private final int arity;
private final int flags;
public AdaptedFunctionReference(int arity, Class owner, String name, String signature, int flags) {
this(arity, NO_RECEIVER, owner, name, signature, flags);
}
public AdaptedFunctionReference(int arity, Object receiver, Class owner, String name, String signature, int flags) {
this.receiver = receiver;
this.owner = owner;
this.name = name;
this.signature = signature;
this.isTopLevel = (flags & 1) == 1;
this.arity = arity;
this.flags = flags >> 1;
}
public KDeclarationContainer getOwner() {
return owner == null ? null :
isTopLevel ? Reflection.getOrCreateKotlinPackage(owner) : Reflection.getOrCreateKotlinClass(owner);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AdaptedFunctionReference)) return false;
AdaptedFunctionReference other = (AdaptedFunctionReference) o;
return isTopLevel == other.isTopLevel &&
arity == other.arity &&
flags == other.flags &&
Intrinsics.areEqual(receiver, other.receiver) &&
Intrinsics.areEqual(owner, other.owner) &&
name.equals(other.name) &&
signature.equals(other.signature);
}
@Override
public int hashCode() {
int result = receiver != null ? receiver.hashCode() : 0;
result = result * 31 + (owner != null ? owner.hashCode() : 0);
result = result * 31 + name.hashCode();
result = result * 31 + signature.hashCode();
result = result * 31 + (isTopLevel ? 1231 : 1237);
result = result * 31 + arity;
result = result * 31 + flags;
return result;
}
}
@@ -3180,6 +3180,15 @@ public abstract interface class kotlin/jvm/functions/FunctionN : kotlin/Function
public abstract fun invoke ([Ljava/lang/Object;)Ljava/lang/Object; public abstract fun invoke ([Ljava/lang/Object;)Ljava/lang/Object;
} }
public class kotlin/jvm/internal/AdaptedFunctionReference {
protected final field receiver Ljava/lang/Object;
public fun <init> (ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
public fun <init> (ILjava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
public fun equals (Ljava/lang/Object;)Z
public fun getOwner ()Lkotlin/reflect/KDeclarationContainer;
public fun hashCode ()I
}
public final class kotlin/jvm/internal/ArrayIteratorKt { public final class kotlin/jvm/internal/ArrayIteratorKt {
public static final fun iterator ([Ljava/lang/Object;)Ljava/util/Iterator; public static final fun iterator ([Ljava/lang/Object;)Ljava/util/Iterator;
} }