Unbox bound receiver if inline class type expected
This commit is contained in:
@@ -37,7 +37,7 @@ internal class KFunctionImpl private constructor(
|
|||||||
name: String,
|
name: String,
|
||||||
private val signature: String,
|
private val signature: String,
|
||||||
descriptorInitialValue: FunctionDescriptor?,
|
descriptorInitialValue: FunctionDescriptor?,
|
||||||
private val boundReceiver: Any? = CallableReference.NO_RECEIVER
|
private val rawBoundReceiver: Any? = CallableReference.NO_RECEIVER
|
||||||
) : KCallableImpl<Any?>(), KFunction<Any?>, FunctionBase<Any?>, FunctionWithAllInvokes {
|
) : KCallableImpl<Any?>(), KFunction<Any?>, FunctionBase<Any?>, FunctionWithAllInvokes {
|
||||||
constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?)
|
constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?)
|
||||||
: this(container, name, signature, null, boundReceiver)
|
: this(container, name, signature, null, boundReceiver)
|
||||||
@@ -49,7 +49,7 @@ internal class KFunctionImpl private constructor(
|
|||||||
descriptor
|
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) {
|
override val descriptor: FunctionDescriptor by ReflectProperties.lazySoft(descriptorInitialValue) {
|
||||||
container.findFunctionDescriptor(name, signature)
|
container.findFunctionDescriptor(name, signature)
|
||||||
@@ -132,6 +132,9 @@ internal class KFunctionImpl private constructor(
|
|||||||
}?.createInlineClassAwareCallerIfNeeded(descriptor, isDefault = true)
|
}?.createInlineClassAwareCallerIfNeeded(descriptor, isDefault = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val boundReceiver
|
||||||
|
get() = rawBoundReceiver.coerceToExpectedReceiverType(descriptor)
|
||||||
|
|
||||||
private fun createStaticMethodCaller(member: Method) =
|
private fun createStaticMethodCaller(member: Method) =
|
||||||
if (isBound) CallerImpl.Method.BoundStatic(member, boundReceiver) else CallerImpl.Method.Static(member)
|
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 {
|
override fun equals(other: Any?): Boolean {
|
||||||
val that = other.asKFunctionImpl() ?: return false
|
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 =
|
override fun hashCode(): Int =
|
||||||
|
|||||||
@@ -21,17 +21,14 @@ import kotlin.reflect.KMutableProperty
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import kotlin.reflect.full.IllegalPropertyDelegateAccessException
|
import kotlin.reflect.full.IllegalPropertyDelegateAccessException
|
||||||
import kotlin.reflect.jvm.internal.JvmPropertySignature.*
|
import kotlin.reflect.jvm.internal.JvmPropertySignature.*
|
||||||
import kotlin.reflect.jvm.internal.calls.Caller
|
import kotlin.reflect.jvm.internal.calls.*
|
||||||
import kotlin.reflect.jvm.internal.calls.CallerImpl
|
|
||||||
import kotlin.reflect.jvm.internal.calls.ThrowingCaller
|
|
||||||
import kotlin.reflect.jvm.internal.calls.createInlineClassAwareCallerIfNeeded
|
|
||||||
|
|
||||||
internal abstract class KPropertyImpl<out R> private constructor(
|
internal abstract class KPropertyImpl<out R> private constructor(
|
||||||
override val container: KDeclarationContainerImpl,
|
override val container: KDeclarationContainerImpl,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
val signature: String,
|
val signature: String,
|
||||||
descriptorInitialValue: PropertyDescriptor?,
|
descriptorInitialValue: PropertyDescriptor?,
|
||||||
val boundReceiver: Any?
|
private val rawBoundReceiver: Any?
|
||||||
) : KCallableImpl<R>(), KProperty<R> {
|
) : KCallableImpl<R>(), KProperty<R> {
|
||||||
constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?) : this(
|
constructor(container: KDeclarationContainerImpl, name: String, signature: String, boundReceiver: Any?) : this(
|
||||||
container, name, signature, null, boundReceiver
|
container, name, signature, null, boundReceiver
|
||||||
@@ -45,7 +42,10 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
|||||||
CallableReference.NO_RECEIVER
|
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 {
|
private val _javaField = ReflectProperties.lazySoft {
|
||||||
val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)
|
val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)
|
||||||
@@ -115,7 +115,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
|||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
val that = other.asKPropertyImpl() ?: return false
|
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 =
|
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<*> {
|
private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Boolean): Caller<*> {
|
||||||
if (KDeclarationContainerImpl.LOCAL_PROPERTY_SIGNATURE.matches(property.signature)) {
|
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 {
|
fun computeFieldCaller(field: Field): CallerImpl<Field> = when {
|
||||||
property.descriptor.isJvmFieldPropertyInCompanionObject() || !Modifier.isStatic(field.modifiers) ->
|
property.descriptor.isJvmFieldPropertyInCompanionObject() || !Modifier.isStatic(field.modifiers) ->
|
||||||
if (isGetter)
|
if (isGetter)
|
||||||
if (isBound) CallerImpl.FieldGetter.BoundInstance(field, property.boundReceiver)
|
if (isBound) CallerImpl.FieldGetter.BoundInstance(field, boundReceiver)
|
||||||
else CallerImpl.FieldGetter.Instance(field)
|
else CallerImpl.FieldGetter.Instance(field)
|
||||||
else
|
else
|
||||||
if (isBound) CallerImpl.FieldSetter.BoundInstance(field, isNotNullProperty(), property.boundReceiver)
|
if (isBound) CallerImpl.FieldSetter.BoundInstance(field, isNotNullProperty(), boundReceiver)
|
||||||
else CallerImpl.FieldSetter.Instance(field, isNotNullProperty())
|
else CallerImpl.FieldSetter.Instance(field, isNotNullProperty())
|
||||||
isJvmStaticProperty() ->
|
isJvmStaticProperty() ->
|
||||||
if (isGetter)
|
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")
|
property.javaField ?: throw KotlinReflectionInternalError("No accessors or field is found for property $property")
|
||||||
)
|
)
|
||||||
!Modifier.isStatic(accessor.modifiers) ->
|
!Modifier.isStatic(accessor.modifiers) ->
|
||||||
if (isBound) CallerImpl.Method.BoundInstance(accessor, property.boundReceiver)
|
if (isBound) CallerImpl.Method.BoundInstance(accessor, boundReceiver)
|
||||||
else CallerImpl.Method.Instance(accessor)
|
else CallerImpl.Method.Instance(accessor)
|
||||||
isJvmStaticProperty() ->
|
isJvmStaticProperty() ->
|
||||||
if (isBound) CallerImpl.Method.BoundJvmStaticInObject(accessor)
|
if (isBound) CallerImpl.Method.BoundJvmStaticInObject(accessor)
|
||||||
else CallerImpl.Method.JvmStaticInObject(accessor)
|
else CallerImpl.Method.JvmStaticInObject(accessor)
|
||||||
else ->
|
else ->
|
||||||
if (isBound) CallerImpl.Method.BoundStatic(accessor, property.boundReceiver)
|
if (isBound) CallerImpl.Method.BoundStatic(accessor, boundReceiver)
|
||||||
else CallerImpl.Method.Static(accessor)
|
else CallerImpl.Method.Static(accessor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +250,7 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool
|
|||||||
else jvmSignature.setterMethod ?: throw KotlinReflectionInternalError(
|
else jvmSignature.setterMethod ?: throw KotlinReflectionInternalError(
|
||||||
"No source found for setter of Java method property: ${jvmSignature.getterMethod}"
|
"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)
|
else CallerImpl.Method.Instance(method)
|
||||||
}
|
}
|
||||||
is MappedKotlinProperty -> {
|
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" }
|
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)
|
else CallerImpl.Method.Instance(accessor)
|
||||||
}
|
}
|
||||||
}.createInlineClassAwareCallerIfNeeded(descriptor)
|
}.createInlineClassAwareCallerIfNeeded(descriptor)
|
||||||
|
|||||||
+29
-19
@@ -74,7 +74,7 @@ internal class InlineClassAwareCaller<out M : Member>(
|
|||||||
|
|
||||||
val unbox = Array(expectedArgsSize) { i ->
|
val unbox = Array(expectedArgsSize) { i ->
|
||||||
if (i in argumentRange) {
|
if (i in argumentRange) {
|
||||||
kotlinParameterTypes[i - shift].toInlineClass()?.getUnboxMethod()
|
kotlinParameterTypes[i - shift].toInlineClass()?.getUnboxMethod(descriptor)
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,27 +103,10 @@ internal class InlineClassAwareCaller<out M : Member>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Class<*>.getBoxMethod(): Method = try {
|
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) {
|
} catch (e: NoSuchMethodException) {
|
||||||
throw KotlinReflectionInternalError("No box method found in inline class: $this (calling $descriptor)")
|
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(
|
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)
|
(this !is BoundCaller && descriptor.extensionReceiverParameter?.type?.isInlineClassType() == true)
|
||||||
return if (needsInlineAwareCaller) InlineClassAwareCaller(descriptor, this, isDefault) else this
|
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