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 2e10948e [DOCS][Rust] Borrow reference types in match_any! and 
dispatch examples (#932)
2e10948e is described below

commit 2e10948e78656afc93a5e754e71f5c7aa983e89d
Author: Tianqi Chen <[email protected]>
AuthorDate: Thu Nov 5 10:02:14 2026 -0500

    [DOCS][Rust] Borrow reference types in match_any! and dispatch examples 
(#932)
    
    Updates the Rust guide and the `#[dispatch]` rustdoc example to borrow
    managed references and values in place, as #931 allows, in place of
    object types or owned bindings that clone.
    
    - **`match_any!`:** `tvm_ffi::String(ref s)` and `Array<Any>(ref arr)`
    borrow without a reference-count change. The text explains `Type(ref
    name)` and keeps `ArrayObj(ref node)` as the way to borrow the object
    node.
    - **Dispatching:** the handlers take `&Array<Any>` and
    `&tvm_ffi::String`. The expansion shown and the handler rule (`&Type`
    becomes a `Type(ref value)` arm) match.
    - **`Any` and `AnyView`:** the example borrows
    `downcast_ref::<Array<i64>>()`, and the description covers managed
    references, values and object types, with the strict, non-converting
    check.
    - **Borrowed values into `Any`:** `label_of` takes `&Point` in place of
    `&PointObj`; its fields are reachable through `Deref`.
---
 docs/guides/rust_lang_guide.rst | 41 ++++++++++++++++++++++-------------------
 rust/tvm-ffi/src/lib.rs         |  2 +-
 2 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/docs/guides/rust_lang_guide.rst b/docs/guides/rust_lang_guide.rst
index 829d3b66..a7d238a2 100644
--- a/docs/guides/rust_lang_guide.rst
+++ b/docs/guides/rust_lang_guide.rst
@@ -83,7 +83,6 @@ the value it borrows. A number and a built-in array 
illustrate owning and borrow
 
 .. code-block:: rust
 
-   use tvm_ffi::collections::array::ArrayObj;
    use tvm_ffi::{Any, AnyView, Array};
 
    let number = Any::from(3_i64);
@@ -91,15 +90,18 @@ the value it borrows. A number and a built-in array 
illustrate owning and borrow
 
    let value = Any::from(Array::from_vec(vec![1_i64, 2, 3]));
    let view = AnyView::from(&value); // Borrow the value without a new 
reference.
-   assert_eq!(view.downcast_ref::<ArrayObj>().unwrap().size, 3);
+   let borrowed: &Array<i64> = view.downcast_ref::<Array<i64>>().unwrap();
+   assert_eq!(borrowed.len(), 3);
 
    let array = value.try_as::<Array<i64>>().unwrap(); // Acquire another 
strong reference.
    assert_eq!(array.len(), 3);
 
-Both ``Any`` and ``AnyView`` provide object-only ``downcast_ref::<T>() -> 
Option<&T>``,
-with ``T: ObjectCore``. It accepts the runtime type or a compatible base type 
and
-returns ``None`` for unrelated types and non-object values. The returned 
reference
-borrows its source without consuming it or incrementing the reference count.
+Both ``Any`` and ``AnyView`` provide ``downcast_ref::<T>() -> Option<&T>``, 
which borrows
+the value in place as a managed reference such as ``Array<i64>``, a value such 
as
+``tvm_ffi::String`` or ``i64``, or an object type such as ``ArrayObj``. The 
check is
+strict, as in ``try_as``, and never converts; it returns ``None`` for other 
types. The
+returned reference borrows its source without consuming it or incrementing the
+reference count.
 In contrast, ``try_as::<Array<i64>>()`` returns an owned managed reference, 
which retains
 the object independently of the source ``Any`` or ``AnyView``.
 
@@ -408,14 +410,14 @@ Converting Borrowed Values into ``Any``
 
 ``Any::from(value)`` takes ownership of ``value``. Use it when you own the 
value.
 When you only have a shared reference—for example, a field accessed through
-``&PointObj``—you cannot move the field into an ``Any``. Call
+``&Point``—you cannot move the field into an ``Any``. Call
 ``AnyCompatible::to_any()`` instead:
 
 .. code-block:: rust
 
    use tvm_ffi::{Any, AnyCompatible};
 
-   fn label_of(point: &PointObj) -> Any {
+   fn label_of(point: &Point) -> Any {
        point.label.to_any()
    }
 
@@ -488,8 +490,8 @@ arm whose type matches the value runs:
        match_any! {
            value {
                i64(n) => format!("integer {n}"),
-               tvm_ffi::String(s) => format!("string {}", s.as_str()),
-               Array<Any>(arr) => format!("array of {} items", arr.len()),
+               tvm_ffi::String(ref s) => format!("string {}", s.as_str()),
+               Array<Any>(ref arr) => format!("array of {} items", arr.len()),
                _ => "something else".to_string(),
            }
        }
@@ -513,9 +515,10 @@ The output is:
    array of 3 items
    something else
 
-``Type(name)`` binds an owned value. For an object, an arm can instead name the
-object type and borrow it, as in ``ArrayObj(ref arr)``, which reads its fields
-without changing the reference count. The final ``_`` arm is required:
+``Type(name)`` binds an owned value. ``Type(ref name)`` instead borrows the 
value
+in place, as the string and array arms above do, without changing any reference
+count; prefer it when the arm only reads. An arm can also name the object type,
+as in ``ArrayObj(ref node)``, to borrow the object node. The final ``_`` arm 
is required:
 new types can be registered at any time, so no list of arms is exhaustive.
 
 Dispatching
@@ -535,7 +538,7 @@ them. Let's describe nested arrays, with a separator 
between items:
 
    #[dispatch(describe, (AnyView<'_>, &str), String)]
    impl Describer {
-       fn describe_array(&self, arr: Array<Any>, sep: &str) -> String {
+       fn describe_array(&self, arr: &Array<Any>, sep: &str) -> String {
            let items: Vec<String> = arr
                .iter()
                .map(|item| {
@@ -550,7 +553,7 @@ them. Let's describe nested arrays, with a separator 
between items:
            value.to_string()
        }
 
-       fn describe_str(&self, value: tvm_ffi::String) -> String {
+       fn describe_str(&self, value: &tvm_ffi::String) -> String {
            value.to_string()
        }
    }
@@ -586,9 +589,9 @@ a ``match_any!`` and a |rs-dispatcher|_ implementation:
        pub fn dispatch(&self, value: AnyView<'_>, sep: &str) -> Option<String> 
{
            match_any! {
                value {
-                   Array<Any>(arr) => Some(self.describe_array(arr, 
sep).into()),
+                   Array<Any>(ref arr) => Some(self.describe_array(arr, 
sep).into()),
                    i64(value) => Some(self.describe_int(value).into()),
-                   tvm_ffi::String(value) => 
Some(self.describe_str(value).into()),
+                   tvm_ffi::String(ref value) => 
Some(self.describe_str(value).into()),
                    _ => None,
                }
            }
@@ -602,8 +605,8 @@ a ``match_any!`` and a |rs-dispatcher|_ implementation:
    }
 
 Each handler becomes one arm, in source order, and its parameter type selects
-the values it matches; a ``&NodeObj`` parameter becomes a ``NodeObj(ref node)``
-arm. The attribute appends ``_ => None``, so a type without a handler returns
+the values it matches; a ``&Type`` parameter becomes a ``Type(ref value)`` arm,
+which borrows the value in place. The attribute appends ``_ => None``, so a 
type without a handler returns
 ``None`` instead of failing. The ``Dispatcher`` implementation lets generic
 code call the same match through one trait.
 
diff --git a/rust/tvm-ffi/src/lib.rs b/rust/tvm-ffi/src/lib.rs
index 66d60f13..951a00a1 100644
--- a/rust/tvm-ffi/src/lib.rs
+++ b/rust/tvm-ffi/src/lib.rs
@@ -139,7 +139,7 @@ pub use crate::type_traits::AnyCompatible;
 ///         format!("integer {value}")
 ///     }
 ///
-///     fn describe_str(&self, value: tvm_ffi::String) -> String {
+///     fn describe_str(&self, value: &tvm_ffi::String) -> String {
 ///         format!("string {}", value.as_str())
 ///     }
 /// }

Reply via email to