[FEAT][RUST] Support runtime-checked try_cast between ObjectRef types#684
[FEAT][RUST] Support runtime-checked try_cast between ObjectRef types#684Seven-Streams wants to merge 6 commits into
Conversation
Signed-off-by: yuchuan <yuchuan.7streams@gmail.com>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
try_cast between any object-based structs.| data.data_union.v_obj = | ||
| data_ptr as *mut ContainerType as *mut #tvm_ffi_crate::tvm_ffi_sys::TVMFFIObject; | ||
| let object_ptr = | ||
| data_ptr as *mut ContainerType as *mut #tvm_ffi_crate::tvm_ffi_sys::TVMFFIObject; |
There was a problem hiding this comment.
Why the order is changed
There was a problem hiding this comment.
We need the object pointer first because the type index is now read from the runtime object header instead of ContainerType::type_index(), which preserves the dynamic subtype after an upcast.
| // Every registered object is an instance of the root Object type. | ||
| if target_type_index == object_begin { |
There was a problem hiding this comment.
not sure if it's necessary
There was a problem hiding this comment.
I think it is. this is the root object fast path. Every object-range type must cast to objectref, and the C++ uses the same range check while avoiding type-table lookups.
There was a problem hiding this comment.
given this is runtime check, likely not having the specialization is ok, depending on how freq conversion to ObjectRef is.
| // Every registered object is an instance of the root Object type. | ||
| if target_type_index == object_begin { |
There was a problem hiding this comment.
given this is runtime check, likely not having the specialization is ok, depending on how freq conversion to ObjectRef is.
| if object_info.is_null() || target_info.is_null() { | ||
| return false; | ||
| } | ||
| let target_depth = (*target_info).type_depth; |
There was a problem hiding this comment.
might worthcheck other template trick for target_type_index. Note in the case of C++ TargetType can be a type T, where things like type_depth can be directly queried as a compile time constant rather than runtime
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
This PR adds direct, runtime-checked casting between Rust object handles, mirroring C++
ObjectRef::as<T>/Downcast<T>.ObjectRefCast is blanket-implemented for types implementing both
ObjectRefCoreandAnyCompatible.try_cast::<B>(self)consumes the source and, on success, rewraps the same object asBwithout cloning or copying it. A failed cast returns aTypeErrordescribing the source and target types.Target compatibility is delegated to
B::check_any_strict. ObjectRef hierarchies acceptBand its runtime subtypes, while parameterized containers use their complete type semantics.The direct
A -> Bpath reuses the existingAnyCompatibleconversion traits through a rawTVMFFIAny, so callers do not need to construct anAnyorAnyView. It first creates a non-owning view for the target check and transfers ownership only after that check succeeds, keeping failure and panic paths leak-free.Derived ObjectRef conversions preserve the runtime type index stored in the object header. A derived object upcast to a base handle can therefore still round-trip through
AnyorAnyViewand downcast correctly.A hidden
is_instance_ofhelper provides hierarchy checks for derive-generated object containers. The cast path usesassert_uncheckedafter establishing the object type-index invariant; release codegen confirms that the intermediateTVMFFIAnystorage and redundant object-range check are eliminated.The PR also includes the derive fixes required by downstream crates and focused tests covering hierarchy casts, failure ownership, dynamic-type preservation through
Any/AnyView, directtry_cast_from_any_view, and parameterized-container mismatch.