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.