This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new bd82ca5f [Rust] MutationView::downcast_ref borrows managed references 
in place (#935)
bd82ca5f is described below

commit bd82ca5f2dcfa8cd384042f9d51a0aab79c8bcf1
Author: Tianqi Chen <[email protected]>
AuthorDate: Thu Nov 5 19:42:37 2026 -0500

    [Rust] MutationView::downcast_ref borrows managed references in place (#935)
    
    `MutationView::downcast_ref` now borrows anything
    `AnyView::downcast_ref` does: a managed reference such as `Array<i64>`
    or `Add`, an object type such as `ArrayObj`, or `Any`. It took only
    object types before, so a mutation handler had to inspect `&AddObj`
    where visit and map handlers already get `&Add`.
    
    ```rust
    let array: &Array<i64> = value.downcast_ref::<Array<i64>>().unwrap();
    ```
    
    The check stays strict, and the borrow is in place with no
    reference-count bump. The Rust guide's mutation section says so.
---
 docs/guides/rust_lang_guide.rst             |  6 +++---
 rust/tvm-ffi/src/extra/structural_mutate.rs | 25 +++++++++++--------------
 2 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/docs/guides/rust_lang_guide.rst b/docs/guides/rust_lang_guide.rst
index a7d238a2..c9f30265 100644
--- a/docs/guides/rust_lang_guide.rst
+++ b/docs/guides/rust_lang_guide.rst
@@ -979,9 +979,9 @@ or panic. State remains available after the recursive call.
 
 Typed ``MutationView<'_, T>`` inputs work with the same recursive methods.
 Use ``value.with_inplace_mode(InplaceMode::Disallow)`` to restrict permission.
-Inspect an object through ``value.downcast_ref::<NodeObj>()`` or other payloads
-through ``value.as_any_view()``; finish using those borrows before consuming 
the
-capability. A typed object capability also dereferences to its shared node.
+Borrow the value in place through ``value.downcast_ref::<Node>()``, as with
+``AnyView``, or other payloads through ``value.as_any_view()``; finish using 
those
+borrows before consuming the capability. A typed object capability also 
dereferences to its shared node.
 Use ``value.field(|node| &node.a)`` to borrow a direct ``Any`` or owning 
object-handle
 field for recursive mutation. The child capability exclusively borrows its 
parent
 and inherits permission only while that parent is unique; child uniqueness is
diff --git a/rust/tvm-ffi/src/extra/structural_mutate.rs 
b/rust/tvm-ffi/src/extra/structural_mutate.rs
index 1716276c..c724cba5 100644
--- a/rust/tvm-ffi/src/extra/structural_mutate.rs
+++ b/rust/tvm-ffi/src/extra/structural_mutate.rs
@@ -61,7 +61,7 @@ use super::dispatch::Dispatcher;
 use crate::any::{is_plain_inline, Any, AnyView};
 use crate::error::{Error, Result, TYPE_ERROR};
 use crate::function::Function;
-use crate::object::{self, Object, ObjectArc, ObjectCore};
+use crate::object::{self, Object, ObjectArc};
 use crate::reflection::TypeAttrColumn;
 use crate::tvm_ffi_sys::TVMFFIFieldFlagBitMask::{
     kTVMFFIFieldFlagBitMaskSEqHashIgnore, 
kTVMFFIFieldFlagBitSetterIsFunctionObj,
@@ -548,24 +548,21 @@ impl<'a, T> MutationView<'a, T> {
         unsafe { AnyView::from_raw_ffi_any(self.value) }
     }
 
-    /// Borrow an object or subtype as `U` without changing ownership or 
permission.
+    /// Borrow the value as `U` without changing ownership or permission.
     ///
-    /// `U` is an object type such as `ArrayObj`. The reference borrows this 
view and
-    /// cannot survive its consumption.
+    /// `U` is anything [`AnyView::downcast_ref`] borrows: a managed reference 
such as
+    /// `Array<i64>`, an object type such as `ArrayObj`, or [`Any`], borrowed 
in place
+    /// without a reference-count bump. The check is strict, and the reference 
borrows
+    /// this view and cannot survive its consumption.
     ///
     /// # Returns
     ///
-    /// The borrowed object, or `None` when the value is not a `U`.
+    /// The borrowed value, or `None` when the value is not a `U`.
     #[inline(always)]
-    pub fn downcast_ref<U: ObjectCore>(&self) -> Option<&U> {
-        if self.value.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin 
as i32
-            || !object::is_instance_of::<U>(self.value.type_index)
-        {
-            return None;
-        }
-        // SAFETY: the type check establishes U's layout; the capability keeps
-        // the allocation borrowed for the lifetime of the returned reference.
-        Some(unsafe { &*self.value.data_union.v_obj.cast::<U>() })
+    pub fn downcast_ref<U: crate::type_traits::DowncastRefFromAny>(&self) -> 
Option<&U> {
+        // SAFETY: the view holds a valid cell, borrowed for the returned 
lifetime,
+        // and the input owner keeps its payload live.
+        unsafe { U::downcast_ref_from_any(&self.value) }
     }
 
     /// Narrow the matched type without acquiring an owning reference.

Reply via email to