diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt index 89d3c4d91c9..7f223d520c3 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt @@ -37,7 +37,7 @@ internal class KFunctionImpl private constructor( name: String, private val signature: String, descriptorInitialValue: FunctionDescriptor?, - private val boundReceiver: Any? = CallableReference.NO_RECEIVER + private val rawBoundReceiver: Any? = CallableReference.NO_RECEIVER ) : KCallableImpl(), KFunction, FunctionBase, FunctionWithAllInvokes { constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?) : this(container, name, signature, null, boundReceiver) @@ -49,7 +49,7 @@ internal class KFunctionImpl private constructor( descriptor ) - override val isBound: Boolean get() = boundReceiver != CallableReference.NO_RECEIVER + override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER override val descriptor: FunctionDescriptor by ReflectProperties.lazySoft(descriptorInitialValue) { container.findFunctionDescriptor(name, signature) @@ -132,6 +132,9 @@ internal class KFunctionImpl private constructor( }?.createInlineClassAwareCallerIfNeeded(descriptor, isDefault = true) } + private val boundReceiver + get() = rawBoundReceiver.coerceToExpectedReceiverType(descriptor) + private fun createStaticMethodCaller(member: Method) = if (isBound) CallerImpl.Method.BoundStatic(member, boundReceiver) else CallerImpl.Method.Static(member) @@ -163,7 +166,7 @@ internal class KFunctionImpl private constructor( override fun equals(other: Any?): Boolean { val that = other.asKFunctionImpl() ?: return false - return container == that.container && name == that.name && signature == that.signature && boundReceiver == that.boundReceiver + return container == that.container && name == that.name && signature == that.signature && rawBoundReceiver == that.rawBoundReceiver } override fun hashCode(): Int = diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt index 774d26a20b8..0b3c6b9546d 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -21,17 +21,14 @@ import kotlin.reflect.KMutableProperty import kotlin.reflect.KProperty import kotlin.reflect.full.IllegalPropertyDelegateAccessException import kotlin.reflect.jvm.internal.JvmPropertySignature.* -import kotlin.reflect.jvm.internal.calls.Caller -import kotlin.reflect.jvm.internal.calls.CallerImpl -import kotlin.reflect.jvm.internal.calls.ThrowingCaller -import kotlin.reflect.jvm.internal.calls.createInlineClassAwareCallerIfNeeded +import kotlin.reflect.jvm.internal.calls.* internal abstract class KPropertyImpl private constructor( override val container: KDeclarationContainerImpl, override val name: String, val signature: String, descriptorInitialValue: PropertyDescriptor?, - val boundReceiver: Any? + private val rawBoundReceiver: Any? ) : KCallableImpl(), KProperty { constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?) : this( container, name, signature, null, boundReceiver @@ -45,7 +42,10 @@ internal abstract class KPropertyImpl private constructor( CallableReference.NO_RECEIVER ) - override val isBound: Boolean get() = boundReceiver != CallableReference.NO_RECEIVER + val boundReceiver + get() = rawBoundReceiver.coerceToExpectedReceiverType(descriptor) + + override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER private val _javaField = ReflectProperties.lazySoft { val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor) @@ -115,7 +115,7 @@ internal abstract class KPropertyImpl private constructor( override fun equals(other: Any?): Boolean { val that = other.asKPropertyImpl() ?: return false - return container == that.container && name == that.name && signature == that.signature && boundReceiver == that.boundReceiver + return container == that.container && name == that.name && signature == that.signature && rawBoundReceiver == that.rawBoundReceiver } override fun hashCode(): Int = @@ -174,6 +174,8 @@ internal abstract class KPropertyImpl private constructor( } } +internal val KPropertyImpl.Accessor<*, *>.boundReceiver + get() = property.boundReceiver private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Boolean): Caller<*> { if (KDeclarationContainerImpl.LOCAL_PROPERTY_SIGNATURE.matches(property.signature)) { @@ -189,10 +191,10 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool fun computeFieldCaller(field: Field): CallerImpl = when { property.descriptor.isJvmFieldPropertyInCompanionObject() || !Modifier.isStatic(field.modifiers) -> if (isGetter) - if (isBound) CallerImpl.FieldGetter.BoundInstance(field, property.boundReceiver) + if (isBound) CallerImpl.FieldGetter.BoundInstance(field, boundReceiver) else CallerImpl.FieldGetter.Instance(field) else - if (isBound) CallerImpl.FieldSetter.BoundInstance(field, isNotNullProperty(), property.boundReceiver) + if (isBound) CallerImpl.FieldSetter.BoundInstance(field, isNotNullProperty(), boundReceiver) else CallerImpl.FieldSetter.Instance(field, isNotNullProperty()) isJvmStaticProperty() -> if (isGetter) @@ -229,13 +231,13 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool property.javaField ?: throw KotlinReflectionInternalError("No accessors or field is found for property $property") ) !Modifier.isStatic(accessor.modifiers) -> - if (isBound) CallerImpl.Method.BoundInstance(accessor, property.boundReceiver) + if (isBound) CallerImpl.Method.BoundInstance(accessor, boundReceiver) else CallerImpl.Method.Instance(accessor) isJvmStaticProperty() -> if (isBound) CallerImpl.Method.BoundJvmStaticInObject(accessor) else CallerImpl.Method.JvmStaticInObject(accessor) else -> - if (isBound) CallerImpl.Method.BoundStatic(accessor, property.boundReceiver) + if (isBound) CallerImpl.Method.BoundStatic(accessor, boundReceiver) else CallerImpl.Method.Static(accessor) } } @@ -248,7 +250,7 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool else jvmSignature.setterMethod ?: throw KotlinReflectionInternalError( "No source found for setter of Java method property: ${jvmSignature.getterMethod}" ) - if (isBound) CallerImpl.Method.BoundInstance(method, property.boundReceiver) + if (isBound) CallerImpl.Method.BoundInstance(method, boundReceiver) else CallerImpl.Method.Instance(method) } is MappedKotlinProperty -> { @@ -261,7 +263,7 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool assert(!Modifier.isStatic(accessor.modifiers)) { "Mapped property cannot have a static accessor: $property" } - return if (isBound) CallerImpl.Method.BoundInstance(accessor, property.boundReceiver) + return if (isBound) CallerImpl.Method.BoundInstance(accessor, boundReceiver) else CallerImpl.Method.Instance(accessor) } }.createInlineClassAwareCallerIfNeeded(descriptor) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt index 550689af156..3e1e33f4b1b 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt @@ -74,7 +74,7 @@ internal class InlineClassAwareCaller( val unbox = Array(expectedArgsSize) { i -> if (i in argumentRange) { - kotlinParameterTypes[i - shift].toInlineClass()?.getUnboxMethod() + kotlinParameterTypes[i - shift].toInlineClass()?.getUnboxMethod(descriptor) } else null } @@ -103,27 +103,10 @@ internal class InlineClassAwareCaller( } private fun Class<*>.getBoxMethod(): Method = try { - getDeclaredMethod("box" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS, getUnboxMethod().returnType) + getDeclaredMethod("box" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS, getUnboxMethod(descriptor).returnType) } catch (e: NoSuchMethodException) { throw KotlinReflectionInternalError("No box method found in inline class: $this (calling $descriptor)") } - - private fun Class<*>.getUnboxMethod(): Method = try { - getDeclaredMethod("unbox" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS) - } catch (e: NoSuchMethodException) { - throw KotlinReflectionInternalError("No unbox method found in inline class: $this (calling $descriptor)") - } - - private fun KotlinType.toInlineClass(): Class<*>? { - val descriptor = constructor.declarationDescriptor - if (descriptor is ClassDescriptor && descriptor.isInline) { - return descriptor.toJavaClass() ?: throw KotlinReflectionInternalError( - "Class object for the class ${descriptor.name} cannot be found (classId=${descriptor.classId})" - ) - } - - return null - } } internal fun CallerImpl.createInlineClassAwareCallerIfNeeded( @@ -136,3 +119,30 @@ internal fun CallerImpl.createInlineClassAwareCallerIfNeeded( (this !is BoundCaller && descriptor.extensionReceiverParameter?.type?.isInlineClassType() == true) return if (needsInlineAwareCaller) InlineClassAwareCaller(descriptor, this, isDefault) else this } + +internal fun Class<*>.getUnboxMethod(descriptor: CallableMemberDescriptor): Method = try { + getDeclaredMethod("unbox" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS) +} catch (e: NoSuchMethodException) { + throw KotlinReflectionInternalError("No unbox method found in inline class: $this (calling $descriptor)") +} + +internal fun KotlinType.toInlineClass(): Class<*>? { + val descriptor = constructor.declarationDescriptor + if (descriptor is ClassDescriptor && descriptor.isInline) { + return descriptor.toJavaClass() ?: throw KotlinReflectionInternalError( + "Class object for the class ${descriptor.name} cannot be found (classId=${descriptor.classId})" + ) + } + + return null +} + +internal fun Any?.coerceToExpectedReceiverType(descriptor: CallableMemberDescriptor): Any? { + val expectedReceiverType = + descriptor.extensionReceiverParameter?.type + ?: (descriptor.containingDeclaration as? ClassDescriptor)?.defaultType + + val unboxMethod = expectedReceiverType?.toInlineClass()?.getUnboxMethod(descriptor) ?: return this + + return unboxMethod.invoke(this) +} \ No newline at end of file