Unbox bound receiver if inline class type expected
This commit is contained in:
@@ -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<Any?>(), KFunction<Any?>, FunctionBase<Any?>, 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 =
|
||||
|
||||
@@ -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<out R> private constructor(
|
||||
override val container: KDeclarationContainerImpl,
|
||||
override val name: String,
|
||||
val signature: String,
|
||||
descriptorInitialValue: PropertyDescriptor?,
|
||||
val boundReceiver: Any?
|
||||
private val rawBoundReceiver: Any?
|
||||
) : KCallableImpl<R>(), KProperty<R> {
|
||||
constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?) : this(
|
||||
container, name, signature, null, boundReceiver
|
||||
@@ -45,7 +42,10 @@ internal abstract class KPropertyImpl<out R> 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<out R> 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<out R> 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<Field> = 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)
|
||||
|
||||
+29
-19
@@ -74,7 +74,7 @@ internal class InlineClassAwareCaller<out M : Member>(
|
||||
|
||||
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<out M : Member>(
|
||||
}
|
||||
|
||||
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 <M : Member> CallerImpl<M>.createInlineClassAwareCallerIfNeeded(
|
||||
@@ -136,3 +119,30 @@ internal fun <M : Member> CallerImpl<M>.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)
|
||||
}
|
||||
Reference in New Issue
Block a user