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 e12d6cdb [Rust] Structural engine readability: one-line comments, 
typed run_visitor, TVMFFIAny by value (#944)
e12d6cdb is described below

commit e12d6cdbb9872bfc64f26c446d20e190339999d7
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Nov 6 12:01:43 2026 -0500

    [Rust] Structural engine readability: one-line comments, typed run_visitor, 
TVMFFIAny by value (#944)
    
    Make the structural visit and mutate engines read straight through, with
    no behavior or public API change. The file layout stays as is; a
    follow-up reorders sections.
    
    - `run_visitor` returns `Result<Option<VisitInterrupt>>`, so
    `visit_root`
      and the two arms of `run_walker` call it directly instead of
      round-tripping a raw result.
    - Private `extern "C-unwind"` helpers take `TVMFFIAny` by value instead
      of its three scalar fields; it is still returned in registers on
      AArch64.
    - One statement of the `_raw` ownership convention per engine file
      replaces the overview blocks; doc and SAFETY comments are one-line
      contracts.
    - Terminology: in-place "mode" and "view" replace "permission" and
      "capability"; `CapabilitySource` -> `MutationSource`,
      `dispatcher_context` -> `dispatcher_ptr`, `handle`/`visitor`/`mutator`
      -> `runtime` for the native prefix, `default_mutate_raw` ->
      `publish_and_descend_raw`, `_scope` & co -> one `_marker`.
    - `VisitErrorContextObj` and its append function move to
      `extra/visit_error_context.rs`, mirroring the C++ header, as
      `update_visit_error_context`. `structural_common.rs` holds the shared
    outlined errors, raw carrier utilities and the reflection prefix helpers
      both engines use (field flags, region rules, field iteration, type-key
      lookup); the callback-chain arity macro moves next to its user in
      `dispatch.rs`. The region guard stays per engine.
    - The borrow-check `compile_fail` examples move out of the user docs
    into
      a doctest-only item in `extra/mod.rs`, where they still run;
      `visit_root`/`mutate_root` get user docs.
    - Drop the in-file `VisitErrorContextObj` layout test: the binding is
      covered end to end by `tests/test_structural_mutate.rs`. Document the
      `backtrace` argument of `Error::new` as most recent call first.
    - `downcast_ref_from_object_in_place` assumes the object-range type
      index read from the object header, as `ObjectRefCore::downcast`
      does, so the borrowing check drops that comparison.
---
 rust/tvm-ffi/src/collections/array.rs         |  15 +-
 rust/tvm-ffi/src/error.rs                     |  19 +-
 rust/tvm-ffi/src/extra/dispatch.rs            |  40 ++-
 rust/tvm-ffi/src/extra/mod.rs                 |  69 ++++
 rust/tvm-ffi/src/extra/structural_common.rs   | 302 +++++++---------
 rust/tvm-ffi/src/extra/structural_map.rs      |   2 +-
 rust/tvm-ffi/src/extra/structural_mutate.rs   | 473 ++++++++------------------
 rust/tvm-ffi/src/extra/structural_visit.rs    | 393 +++++----------------
 rust/tvm-ffi/src/extra/structural_walk.rs     |  23 +-
 rust/tvm-ffi/src/extra/unchanged.rs           |   6 +-
 rust/tvm-ffi/src/extra/visit_error_context.rs | 120 +++++++
 rust/tvm-ffi/src/lib.rs                       |   4 +-
 rust/tvm-ffi/src/match_any_internal.rs        |  28 +-
 rust/tvm-ffi/src/object.rs                    |  23 +-
 rust/tvm-ffi/src/type_traits.rs               |  33 +-
 rust/tvm-ffi/tests/test_structural_mutate.rs  |  82 +++--
 16 files changed, 659 insertions(+), 973 deletions(-)

diff --git a/rust/tvm-ffi/src/collections/array.rs 
b/rust/tvm-ffi/src/collections/array.rs
index 7f824182..24539917 100644
--- a/rust/tvm-ffi/src/collections/array.rs
+++ b/rust/tvm-ffi/src/collections/array.rs
@@ -222,7 +222,7 @@ impl<T: ContainerElement + Clone> Array<T> {
         let size = items.len();
 
         // Allocate with capacity
-        let arc = ObjectArc::<ArrayObj>::new_with_extra_items(ArrayObj {
+        let mut arc = ObjectArc::<ArrayObj>::new_with_extra_items(ArrayObj {
             object: Object::new(),
             data: core::ptr::null_mut(),
             size: size as i64,
@@ -231,16 +231,13 @@ impl<T: ContainerElement + Clone> Array<T> {
         });
 
         unsafe {
-            let raw_ptr = ObjectArc::as_ptr(&arc) as *mut ArrayObj;
-            let container = &mut *raw_ptr;
+            let container = &mut *ObjectArc::as_mut_ptr(&mut arc);
 
             let base_ptr = ArrayObj::extra_items_mut(container).as_mut_ptr();
             container.data = base_ptr as *mut _;
 
             for (i, item) in items.into_iter().enumerate() {
-                let mut raw = TVMFFIAny::new();
-                T::container_move_to_any(item, &mut raw);
-                core::ptr::write(base_ptr.add(i), raw);
+                write_cell(base_ptr.add(i), item);
             }
         }
         // SAFETY: `arc` was allocated and initialized above as an `Array<T>`.
@@ -466,8 +463,6 @@ impl<T: ContainerElement + Clone> Array<T> {
     }
 }
 
-// --- Index Implementation ---
-
 /// Lends `&T` from the array's cell in place. Every cell of an `Array<T>`
 /// holds a `T` (checked when the array is built), so only a debug check runs.
 impl<T: ContainerElement + Clone + RefFromAnyUnchecked> std::ops::Index<usize> 
for Array<T> {
@@ -490,8 +485,6 @@ impl<T: ContainerElement + Clone + RefFromAnyUnchecked> 
std::ops::Index<usize> f
     }
 }
 
-// --- Iterator Implementations ---
-
 impl<T: ContainerElement + Clone + RefFromAnyUnchecked> Array<T> {
     /// Return an iterator that borrows each element in place, without a
     /// reference-count bump, as `array[i]` does.
@@ -609,8 +602,6 @@ impl<T: ContainerElement + Clone> FromIterator<T> for 
Array<T> {
     }
 }
 
-// --- Any Type System Conversions ---
-
 unsafe impl<T> AnyCompatible for Array<T>
 where
     T: ContainerElement + Clone,
diff --git a/rust/tvm-ffi/src/error.rs b/rust/tvm-ffi/src/error.rs
index 5dd42ef8..1fc4e7bd 100644
--- a/rust/tvm-ffi/src/error.rs
+++ b/rust/tvm-ffi/src/error.rs
@@ -73,7 +73,7 @@ pub const INTERNAL_ERROR: ErrorKind = 
ErrorKind::new("InternalError");
 pub const OVERFLOW_ERROR: ErrorKind = ErrorKind::new("OverflowError");
 pub const ZERO_DIVISION_ERROR: ErrorKind = ErrorKind::new("ZeroDivisionError");
 
-/// error object
+/// The object behind an [`Error`]: its kind, message, backtrace, cause and 
context.
 #[repr(C)]
 #[derive(Object)]
 #[type_key = "ffi.Error"]
@@ -177,7 +177,7 @@ impl Error {
     ///
     /// * `kind` - The kind of the error, such as [`VALUE_ERROR`].
     /// * `message` - The message of the error.
-    /// * `backtrace` - The backtrace of the error, which may be empty.
+    /// * `backtrace` - The backtrace of the error, most recent call first; 
may be empty.
     ///
     /// # Returns
     ///
@@ -192,7 +192,7 @@ impl Error {
     ///
     /// * `kind` - The kind of the error.
     /// * `message` - The message of the error.
-    /// * `backtrace` - The backtrace of the error, which may be empty.
+    /// * `backtrace` - The backtrace of the error, most recent call first; 
may be empty.
     /// * `cause_chain` - The error that caused this one, if any.
     /// * `extra_context` - An object of application-specific context, if any.
     ///
@@ -291,11 +291,8 @@ impl Error {
         self.data.cell.backtrace.as_str()
     }
 
-    /// Return the cause, if one was attached to this error.
-    ///
-    /// # Returns
-    ///
-    /// The error that caused this one, or `None`.
+    /// The error that caused this one, the next link of the cause chain, as 
C++
+    /// `cause_chain()`. See also `source`.
     pub fn cause_chain(&self) -> Option<&Error> {
         let handle = &self.data.cell.cause_chain;
         if handle.is_null() {
@@ -306,11 +303,7 @@ impl Error {
         Some(unsafe { &*(handle as *const _ as *const Error) })
     }
 
-    /// Return the application-specific context, if present.
-    ///
-    /// # Returns
-    ///
-    /// The context object, or `None`.
+    /// The application-specific context object, if present.
     pub fn extra_context(&self) -> Option<&object::ObjectRef> {
         let handle = &self.data.cell.extra_context;
         if handle.is_null() {
diff --git a/rust/tvm-ffi/src/extra/dispatch.rs 
b/rust/tvm-ffi/src/extra/dispatch.rs
index 170a11b0..0d749f04 100644
--- a/rust/tvm-ffi/src/extra/dispatch.rs
+++ b/rust/tvm-ffi/src/extra/dispatch.rs
@@ -53,7 +53,7 @@ impl<'a> DispatchInput for AnyView<'a> {
     type Source = crate::match_any_internal::ViewSource<'a>;
 }
 impl<'a, T> DispatchInput for crate::MutationView<'a, T> {
-    type Source = crate::match_any_internal::CapabilitySource<'a>;
+    type Source = crate::match_any_internal::MutationSource<'a>;
 }
 
 // Generated alias bounds must not make recovery depend on a temporary borrow.
@@ -70,7 +70,6 @@ impl<'source, 'value> 
DispatchRecovery<crate::match_any_internal::ViewSource<'so
     type Recovery = ();
 }
 
-use super::structural_common::impl_callback_chain_tuple_arities;
 use std::{borrow::BorrowMut, marker::PhantomData};
 
 /// Inferred selectors for dispatcher normalization.
@@ -101,7 +100,7 @@ pub mod marker {
     pub struct BorrowedObject<T>(PhantomData<fn() -> T>);
     /// Pass the first `AnyView` without a runtime type filter.
     pub enum AnyView {}
-    /// Match a mutation capability for `T`, retaining its scoped permission.
+    /// Match a mutation view for `T`, keeping its in-place mode.
     pub struct Mutation<T = crate::Any>(PhantomData<fn() -> T>);
 }
 
@@ -363,4 +362,39 @@ macro_rules! dispatch_tuple_links {
         }
     };
 }
+// Generate the tuple arities supported by the standard library (1 through 12).
+macro_rules! impl_callback_chain_tuple_arities {
+    ($impl_chain:ident) => {
+        impl_callback_chain_tuple_arities!(
+            @prefixes $impl_chain;
+            [];
+            (F0, M0, 0),
+            (F1, M1, 1),
+            (F2, M2, 2),
+            (F3, M3, 3),
+            (F4, M4, 4),
+            (F5, M5, 5),
+            (F6, M6, 6),
+            (F7, M7, 7),
+            (F8, M8, 8),
+            (F9, M9, 9),
+            (F10, M10, 10),
+            (F11, M11, 11)
+        );
+    };
+    (@prefixes $impl_chain:ident; [$($prefix:tt)*];) => {};
+    (
+        @prefixes $impl_chain:ident;
+        [$($prefix:tt)*];
+        $next:tt $(, $rest:tt)*
+    ) => {
+        $impl_chain!($($prefix)* $next);
+        impl_callback_chain_tuple_arities!(
+            @prefixes $impl_chain;
+            [$($prefix)* $next,];
+            $($rest),*
+        );
+    };
+}
+
 impl_callback_chain_tuple_arities!(dispatch_tuple_links);
diff --git a/rust/tvm-ffi/src/extra/mod.rs b/rust/tvm-ffi/src/extra/mod.rs
index 9b3484f3..3fd2503b 100644
--- a/rust/tvm-ffi/src/extra/mod.rs
+++ b/rust/tvm-ffi/src/extra/mod.rs
@@ -25,3 +25,72 @@ pub mod structural_mutate;
 pub mod structural_visit;
 pub mod structural_walk;
 pub mod unchanged;
+mod visit_error_context;
+
+/// Borrow guarantees of the structural views, checked as `compile_fail` 
doctests.
+///
+/// `StructuralVisitorView::base` cannot outlive its view:
+/// ```compile_fail
+/// use tvm_ffi::{StructuralVisitorObj, StructuralVisitorView};
+/// fn retain<D>(view: &StructuralVisitorView<'_, D>) -> &'static 
StructuralVisitorObj {
+///     view.base()
+/// }
+/// ```
+///
+/// The visitor prefix cannot be converted into an owning FFI value:
+///
+/// ```compile_fail
+/// use tvm_ffi::{Any, StructuralVisitorView};
+/// fn retain<D>(view: &StructuralVisitorView<'_, D>) -> Any {
+///     Any::from(view.base())
+/// }
+/// ```
+///
+/// A node borrowed through a copied `MutationView` cannot survive consumption 
of the view:
+/// ```compile_fail,E0505
+/// use tvm_ffi::{StructuralMutatorView, MutationView};
+/// fn invalid<D>(value: MutationView<'_>, dispatch: &mut D, mutator: &mut 
StructuralMutatorView<'_, D>) {
+///     let view = value.as_any_view();
+///     let copy = view;
+///     let node = 
copy.downcast_ref::<tvm_ffi::collections::array::ArrayObj>().unwrap();
+///     mutator.default_mutate(dispatch, value).unwrap();
+///     println!("{}", node.size);
+/// }
+/// ```
+///
+/// Moving the handle into a nested callback cannot bypass that borrow:
+/// ```compile_fail,E0505
+/// use tvm_ffi::{dispatch, structural_mutate, Any, MutationView, 
StructuralMutatorView, Result, UnchangedOr};
+/// struct Inner<'a>(Option<MutationView<'a>>);
+/// #[dispatch(mutate, (MutationView<'_>, &mut StructuralMutatorView<'_, 
Self>), Result<UnchangedOr<Any>>)]
+/// impl<'a> Inner<'a> {
+///     fn mutate_bool(&mut self, _: bool, mutator: &mut 
StructuralMutatorView<'_, Self>) -> Result<UnchangedOr<Any>> {
+///         let pending = self.0.take().unwrap();
+///         mutator.default_mutate(self, pending)
+///     }
+/// }
+/// fn invalid(value: MutationView<'_>) {
+///     let view = value.as_any_view();
+///     let node = 
view.downcast_ref::<tvm_ffi::collections::array::ArrayObj>().unwrap();
+///     structural_mutate(true, Inner(Some(value))).unwrap();
+///     println!("{}", node.size);
+/// }
+/// ```
+///
+/// A copied inspection view also cannot survive low-level default mutation:
+/// ```compile_fail,E0505
+/// use tvm_ffi::{dispatch, Any, MutationView, StructuralMutatorView, Result, 
Unchanged, UnchangedOr};
+/// struct Pass;
+/// #[dispatch(mutate, (MutationView<'_>, &mut StructuralMutatorView<'_, 
Self>), Result<UnchangedOr<Any>>)]
+/// impl Pass {
+///     fn mutate_any(&mut self, value: MutationView<'_>, mutator: &mut 
StructuralMutatorView<'_, Self>) -> Result<UnchangedOr<Any>> {
+///         let view = value.as_any_view();
+///         let copy = view;
+///         mutator.default_mutate(self, value).unwrap();
+///         println!("{}", copy.type_index());
+///         Ok(Unchanged.into())
+///     }
+/// }
+/// ```
+#[cfg(doctest)]
+pub struct StructuralViewBorrowChecks;
diff --git a/rust/tvm-ffi/src/extra/structural_common.rs 
b/rust/tvm-ffi/src/extra/structural_common.rs
index 8c931e92..cfe39842 100644
--- a/rust/tvm-ffi/src/extra/structural_common.rs
+++ b/rust/tvm-ffi/src/extra/structural_common.rs
@@ -17,12 +17,18 @@
  * under the License.
  */
 
-use crate::any::{Any, AnyView};
-use crate::collections::array::Array;
-use crate::derive::Object;
+use super::structural_visit::DefRegionKind;
+use crate::any::Any;
 use crate::error::{Error, Result, RUNTIME_ERROR};
-use crate::object::{self, Object, ObjectArc, ObjectRef, ObjectRefCore};
-use crate::tvm_ffi_sys::{TVMFFIAny, TVMFFIAnyDataUnion, TVMFFIObject, 
TVMFFITypeIndex};
+use crate::tvm_ffi_sys::TVMFFIFieldFlagBitMask::{
+    kTVMFFIFieldFlagBitMaskSEqHashDefPattern, 
kTVMFFIFieldFlagBitMaskSEqHashDefSimple,
+    kTVMFFIFieldFlagBitMaskSEqHashIgnore, 
kTVMFFIFieldFlagBitSetterIsFunctionObj,
+};
+use crate::tvm_ffi_sys::{
+    TVMFFIAny, TVMFFIByteArray, TVMFFIFieldInfo, TVMFFISEqHashKind, 
TVMFFITypeIndex,
+    TVMFFITypeInfo, TVMFFITypeKeyToIndex,
+};
+use std::ops::ControlFlow;
 
 // 
-----------------------------------------------------------------------------
 // Shared outlined errors
@@ -36,6 +42,12 @@ pub(super) fn runtime_error(message: &str) -> Error {
     Error::new(RUNTIME_ERROR, message, "")
 }
 
+#[cold]
+#[inline(never)]
+pub(super) fn wrong_dispatcher() -> ! {
+    panic!("structural traversal view used with a different dispatcher 
instance")
+}
+
 #[cold]
 #[inline(never)]
 pub(super) fn missing_field_getter_error(operation: &str, name: &str) -> Error 
{
@@ -58,21 +70,13 @@ pub(super) fn with_structural_field_error_context(
 /// inside the cold path instead of successful recursive traversal frames.
 ///
 /// # Safety
-/// The fields must describe one owning TVMFFIAny that has not been consumed.
+/// `raw` is one owning TVMFFIAny that has not been consumed.
 // Perf note: Construct the addressable Any and perform checked Error 
conversion
 // inside this outline boundary, not in the successful recursive caller's 
frame.
 #[cold]
 #[inline(never)]
-pub(super) unsafe fn structural_error_from_raw(
-    type_index: i32,
-    small_str_len: u32,
-    data_union: TVMFFIAnyDataUnion,
-) -> Error {
-    let value = Any::from_raw_ffi_any(TVMFFIAny {
-        type_index,
-        small_str_len,
-        data_union,
-    });
+pub(super) unsafe fn structural_error_from_raw(raw: TVMFFIAny) -> Error {
+    let value = Any::from_raw_ffi_any(raw);
     match Error::try_from(value) {
         Ok(error) | Err(error) => error,
     }
@@ -87,134 +91,6 @@ pub(crate) fn with_structural_error_context(error: Error, 
operation: &str, frame
     Error::with_appended_backtrace(error, &format!("[native structural 
{operation}] {frame}\n"))
 }
 
-/// Rust binding of C++ `VisitErrorContextObj`, the payload that
-/// `Error::extra_context` carries to name the nodes a failed visit unwound 
through.
-#[repr(C)]
-#[derive(Object)]
-#[type_key = "ffi.VisitErrorContext"]
-#[type_final]
-pub(crate) struct VisitErrorContextObj {
-    base: Object,
-    /// Visited nodes, innermost first; C++ `ObjectRef` is nullable.
-    reverse_visit_pattern: Array<Option<ObjectRef>>,
-    /// The `extra_context` the error carried before this context replaced it.
-    prev_error_context: Option<ObjectRef>,
-}
-
-/// Name the visited object in `raw` in the error's visit context, like C++
-/// `detail::UpdateVisitErrorContext`. Copy-on-write at each level: the Error, 
its
-/// context and the context's pattern are each copied only when shared, so an 
error
-/// owned by the unwinding frame is appended in place.
-#[cold]
-pub(crate) fn with_visit_error_context(mut error: Error, raw: TVMFFIAny) -> 
Error {
-    if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
-        return error;
-    }
-    // SAFETY: the traversal input remains live during annotation. Conversion
-    // acquires ownership before the temporary view ends; raw is an object tag.
-    let Ok(node) = ObjectRef::try_from(unsafe { AnyView::from_raw_ffi_any(raw) 
}) else {
-        return error;
-    };
-    let as_context = |context: &ObjectRef| {
-        let object = ObjectArc::as_ptr(ObjectRef::data(context));
-        // SAFETY: `context` keeps its object alive; the type is checked first.
-        unsafe {
-            object::is_instance_of::<VisitErrorContextObj>(
-                (*object.cast::<TVMFFIObject>()).type_index,
-            )
-            .then(|| &*object.cast::<VisitErrorContextObj>())
-        }
-    };
-    // Callback, policy and default descent can report the same frame.
-    if let Some(context) = error.extra_context().and_then(as_context) {
-        if context
-            .reverse_visit_pattern
-            .iter()
-            .next_back()
-            .and_then(Option::as_ref)
-            .is_some_and(|last| last.same_as(&node))
-        {
-            return error;
-        }
-    }
-    let slot = error.extra_context_mut();
-    let previous = slot.take();
-    let context = match previous {
-        Some(previous) if as_context(&previous).is_some() => {
-            // SAFETY: `previous` was checked to be a `VisitErrorContextObj`.
-            let mut context = unsafe {
-                ObjectArc::from_raw(
-                    ObjectArc::into_raw(ObjectRef::into_data(previous))
-                        .cast::<VisitErrorContextObj>(),
-                )
-            };
-            if !ObjectArc::is_unique(&context) {
-                context = ObjectArc::new(VisitErrorContextObj {
-                    base: Object::new(),
-                    reverse_visit_pattern: 
context.reverse_visit_pattern.clone(),
-                    prev_error_context: context.prev_error_context.clone(),
-                });
-            }
-            // SAFETY: this handle is the context's only reference.
-            unsafe {
-                (*ObjectArc::as_mut_ptr(&mut context))
-                    .reverse_visit_pattern
-                    .push(Some(node))
-            };
-            context
-        }
-        previous => ObjectArc::new(VisitErrorContextObj {
-            base: Object::new(),
-            reverse_visit_pattern: Array::from_vec(vec![Some(node)]),
-            prev_error_context: previous,
-        }),
-    };
-    // SAFETY: every object starts with the root `Object` header.
-    *slot = Some(unsafe {
-        ObjectRef::from_data(ObjectArc::from_raw(
-            ObjectArc::into_raw(context).cast::<Object>(),
-        ))
-    });
-    error
-}
-
-// Generate the tuple arities supported by the standard library (1 through 12).
-macro_rules! impl_callback_chain_tuple_arities {
-    ($impl_chain:ident) => {
-        impl_callback_chain_tuple_arities!(
-            @prefixes $impl_chain;
-            [];
-            (F0, M0, 0),
-            (F1, M1, 1),
-            (F2, M2, 2),
-            (F3, M3, 3),
-            (F4, M4, 4),
-            (F5, M5, 5),
-            (F6, M6, 6),
-            (F7, M7, 7),
-            (F8, M8, 8),
-            (F9, M9, 9),
-            (F10, M10, 10),
-            (F11, M11, 11)
-        );
-    };
-    (@prefixes $impl_chain:ident; [$($prefix:tt)*];) => {};
-    (
-        @prefixes $impl_chain:ident;
-        [$($prefix:tt)*];
-        $next:tt $(, $rest:tt)*
-    ) => {
-        $impl_chain!($($prefix)* $next);
-        impl_callback_chain_tuple_arities!(
-            @prefixes $impl_chain;
-            [$($prefix)* $next,];
-            $($rest),*
-        );
-    };
-}
-
-pub(crate) use impl_callback_chain_tuple_arities;
-
 // 
-----------------------------------------------------------------------------
 // Raw carrier utilities
 // 
-----------------------------------------------------------------------------
@@ -258,49 +134,107 @@ pub(crate) unsafe fn raw_ffi_any_into_result(raw: 
TVMFFIAny) -> Result<Any> {
         return Ok(Any::from_raw_ffi_any(raw));
     }
     core::hint::cold_path();
-    Err(structural_error_from_raw(
-        raw.type_index,
-        raw.small_str_len,
-        raw.data_union,
-    ))
+    Err(structural_error_from_raw(raw))
+}
+
+pub(super) const FLAG_SEQ_HASH_IGNORE: i64 = 
kTVMFFIFieldFlagBitMaskSEqHashIgnore as i64;
+pub(super) const FLAG_SEQ_HASH_DEF_PATTERN: i64 = 
kTVMFFIFieldFlagBitMaskSEqHashDefPattern as i64;
+pub(super) const FLAG_SEQ_HASH_DEF_SIMPLE: i64 = 
kTVMFFIFieldFlagBitMaskSEqHashDefSimple as i64;
+pub(super) const FLAG_SETTER_IS_FUNCTION: i64 = 
kTVMFFIFieldFlagBitSetterIsFunctionObj as i64;
+
+/// The runtime type index of the native type `key`; panics when it is 
unregistered.
+#[cold]
+pub(super) fn registered_type_index(key: &str) -> i32 {
+    let mut type_index = 0;
+    // SAFETY: `key` outlives the lookup.
+    if unsafe { TVMFFITypeKeyToIndex(&TVMFFIByteArray::from_str(key), &mut 
type_index) } != 0 {
+        panic!("{key} is not registered: {}", Error::from_raised());
+    }
+    type_index
+}
+
+/// The registered `structural_eq_hash_kind` of `info`, `Unsupported` without 
metadata.
+///
+/// # Safety
+///
+/// `info` is a registered type-info record.
+#[inline(always)]
+pub(super) unsafe fn seq_hash_kind(info: *const TVMFFITypeInfo) -> i32 {
+    let metadata = (*info).metadata;
+    if metadata.is_null() {
+        TVMFFISEqHashKind::kTVMFFISEqHashKindUnsupported as i32
+    } else {
+        (*metadata).structural_eq_hash_kind
+    }
 }
 
-#[cfg(test)]
-mod tests {
-    use super::VisitErrorContextObj;
-    use crate::object::ObjectCore;
+#[inline(always)]
+pub(super) fn field_def_region(field: &TVMFFIFieldInfo, inherited: 
DefRegionKind) -> DefRegionKind {
+    // Precedence: a pattern region propagates; entering any kind inside it 
has no effect.
+    if inherited == DefRegionKind::Pattern {
+        DefRegionKind::Pattern
+    } else if field.flags & FLAG_SEQ_HASH_DEF_SIMPLE != 0 {
+        DefRegionKind::Simple
+    } else if field.flags & FLAG_SEQ_HASH_DEF_PATTERN != 0 {
+        DefRegionKind::Pattern
+    } else {
+        inherited
+    }
+}
 
-    // The binding must match the layout C++ registers for 
`ffi.VisitErrorContext`.
-    #[test]
-    fn visit_error_context_layout_matches_registered_fields() {
-        let expected = [
-            (
-                "reverse_visit_pattern",
-                std::mem::offset_of!(VisitErrorContextObj, 
reverse_visit_pattern),
-            ),
-            (
-                "prev_error_context",
-                std::mem::offset_of!(VisitErrorContextObj, prev_error_context),
-            ),
-        ];
-        // SAFETY: the type is registered by the runtime; its field table 
lives as long.
-        let fields = unsafe {
-            let info = 
crate::tvm_ffi_sys::TVMFFIGetTypeInfo(VisitErrorContextObj::type_index());
-            assert!(!info.is_null());
-            std::slice::from_raw_parts((*info).fields, (*info).num_fields as 
usize)
-        };
-        assert_eq!(fields.len(), expected.len());
-        for (name, offset) in expected {
-            let field = fields
-                .iter()
-                .find(|field| field.name.as_str() == name)
-                .unwrap_or_else(|| panic!("`{name}` is not a registered 
field"));
-            assert_eq!(field.offset as usize, offset, "offset of `{name}`");
-            assert_eq!(
-                field.size as usize,
-                std::mem::size_of::<usize>(),
-                "size of `{name}`"
-            );
+/// A simple definition applies to a FreeVar value itself, but not to
+/// the FreeVar's own reflected children: nested free vars there must resolve
+/// against an outer binding instead of rebinding. Mirrors C++
+/// `VisitReflectedFieldsExpected`.
+#[inline(always)]
+pub(super) fn free_var_child_region(
+    inherited: DefRegionKind,
+    structural_eq_hash_kind: i32,
+) -> DefRegionKind {
+    if inherited == DefRegionKind::Simple
+        && structural_eq_hash_kind == 
TVMFFISEqHashKind::kTVMFFISEqHashKindFreeVar as i32
+    {
+        DefRegionKind::None
+    } else {
+        inherited
+    }
+}
+
+/// Visit every reflected field described by `info` and its ancestors in the
+/// same parent-to-child order as C++ `ForEachFieldInfoWithEarlyStop`.
+///
+/// # Safety
+///
+/// `info` must point to an immortal registered type-info record.
+pub(super) unsafe fn for_each_field_info<B>(
+    info: *const TVMFFITypeInfo,
+    callback: &mut impl FnMut(&'static TVMFFIFieldInfo) -> ControlFlow<B>,
+) -> Option<B> {
+    // Ancestor slot 0 is the root Object. C++ starts at slot 1, walks toward
+    // the immediate parent, then visits the concrete type's own fields.
+    for depth in 1..(*info).type_depth {
+        let ancestor = *(*info).type_acenstors.offset(depth as isize);
+        if let Some(value) = visit_field_level(ancestor, callback) {
+            return Some(value);
+        }
+    }
+    visit_field_level(info, callback)
+}
+
+unsafe fn visit_field_level<B>(
+    info: *const TVMFFITypeInfo,
+    callback: &mut impl FnMut(&'static TVMFFIFieldInfo) -> ControlFlow<B>,
+) -> Option<B> {
+    if info.is_null() || (*info).fields.is_null() {
+        return None;
+    }
+    let fields = std::slice::from_raw_parts((*info).fields, (*info).num_fields 
as usize);
+    for field in fields {
+        // C reflection tables are immortal once registered.
+        let field: &'static TVMFFIFieldInfo = &*(field as *const 
TVMFFIFieldInfo);
+        if let ControlFlow::Break(value) = callback(field) {
+            return Some(value);
         }
     }
+    None
 }
diff --git a/rust/tvm-ffi/src/extra/structural_map.rs 
b/rust/tvm-ffi/src/extra/structural_map.rs
index cf25e3f6..852389fa 100644
--- a/rust/tvm-ffi/src/extra/structural_map.rs
+++ b/rust/tvm-ffi/src/extra/structural_map.rs
@@ -114,7 +114,7 @@ where
         let raw = *value.as_any_view().as_raw_ffi_any();
         let kind = mutator.def_region_kind();
         if PRE_ORDER {
-            // Snapshot permission before a callback can retain or release 
ownership.
+            // Snapshot the mode before a callback can retain or release 
ownership.
             // SAFETY: the input owner remains live through this synchronous 
callback;
             // its higher-ranked view cannot escape into the owning result.
             let Some(callback_result) = self
diff --git a/rust/tvm-ffi/src/extra/structural_mutate.rs 
b/rust/tvm-ffi/src/extra/structural_mutate.rs
index 75aeec40..7a5c433a 100644
--- a/rust/tvm-ffi/src/extra/structural_mutate.rs
+++ b/rust/tvm-ffi/src/extra/structural_mutate.rs
@@ -22,26 +22,8 @@
 //! [`structural_mutate`] lets a mutator drive recursion, while
 //! [`structural_map`] applies callbacks around engine-owned recursion.
 
-// 
-----------------------------------------------------------------------------
-// Implementation overview
-// 
-----------------------------------------------------------------------------
-//
-// This file is organized into:
-// - Data structures and mutation capabilities.
-// - Outlined errors and private utility functions.
-// - Engine implementation and the public entry point.
-//
-// We use narrowly scoped unsafe code for native interoperation and efficient
-// traversal. Safety and ownership contracts are documented at each boundary.
-//
-// The main performance strategies are:
-// - Outline cold work to keep its temporary storage out of recursive frames.
-// - Use _raw helpers and private extern "C-unwind" boundaries for register
-//   transport on AArch64 while preserving Rust unwinding.
-// - Inline small conversions and forwarding code so ownership transfers and
-//   redundant cleanup can optimize away.
-//
-// Local Perf note comments explain individual implementation choices.
+// `_raw` functions move one owned `TVMFFIAny`: forward it once, or import it 
into `Any` before
+// anything can unwind. Private `extern "C-unwind"` helpers return it in 
registers on AArch64.
 
 use std::cell::{RefCell, UnsafeCell};
 use std::collections::{hash_map::Entry, HashMap};
@@ -63,32 +45,27 @@ use crate::error::{Error, Result, TYPE_ERROR};
 use crate::function::Function;
 use crate::object::{self, Object, ObjectArc};
 use crate::reflection::TypeAttrColumn;
-use crate::tvm_ffi_sys::TVMFFIFieldFlagBitMask::{
-    kTVMFFIFieldFlagBitMaskSEqHashIgnore, 
kTVMFFIFieldFlagBitSetterIsFunctionObj,
-};
 use crate::tvm_ffi_sys::{
-    TVMFFIAny, TVMFFIAnyDataUnion, TVMFFIAnyViewToOwnedAny, TVMFFIByteArray, 
TVMFFIFieldInfo,
-    TVMFFIFieldSetter, TVMFFIFunctionCall, TVMFFIGetTypeInfo, TVMFFIObject, 
TVMFFITypeIndex,
-    TVMFFITypeKeyToIndex,
+    TVMFFIAny, TVMFFIAnyViewToOwnedAny, TVMFFIFieldInfo, TVMFFIFieldSetter, 
TVMFFIFunctionCall,
+    TVMFFIGetTypeInfo, TVMFFIObject, TVMFFITypeIndex,
 };
 use crate::tvm_ffi_sys::{TVMFFIObjectHandle, TVMFFISEqHashKind};
 
 use super::structural_common::{
-    missing_field_getter_error, raw_ffi_any_into_result, raw_ffi_any_same_as,
-    result_into_raw_ffi_any, runtime_error, with_structural_error_context,
-    with_structural_field_error_context, with_visit_error_context,
-};
-use super::structural_visit::{
-    field_def_region, for_each_field_info, free_var_child_region, 
DefRegionKind,
+    field_def_region, for_each_field_info, free_var_child_region, 
missing_field_getter_error,
+    raw_ffi_any_into_result, raw_ffi_any_same_as, registered_type_index, 
result_into_raw_ffi_any,
+    runtime_error, seq_hash_kind, with_structural_error_context,
+    with_structural_field_error_context, wrong_dispatcher, 
FLAG_SEQ_HASH_IGNORE,
+    FLAG_SETTER_IS_FUNCTION,
 };
+use super::structural_visit::DefRegionKind;
 use super::unchanged::is_unchanged;
 pub use super::unchanged::{Unchanged, UnchangedOr};
+use super::visit_error_context::update_visit_error_context;
 
 const STRUCTURAL_MUTATE_ATTR: &str = "__s_mutate__";
 const STRUCTURAL_MAYBE_INPLACE_MUTATE_ATTR: &str = 
"__s_maybe_inplace_mutate__";
 const SHALLOW_COPY_ATTR: &str = "__ffi_shallow_copy__";
-const FLAG_SEQ_HASH_IGNORE: i64 = kTVMFFIFieldFlagBitMaskSEqHashIgnore as i64;
-const FLAG_SETTER_IS_FUNCTION: i64 = kTVMFFIFieldFlagBitSetterIsFunctionObj as 
i64;
 
 // 
-----------------------------------------------------------------------------
 // Data structures and FFI layout
@@ -148,7 +125,7 @@ impl StructuralMutatorObj {
 /// state only synchronously, on the calling thread.
 ///
 /// `default_mutate_raw` returns one owning ABI replacement/Unchanged/Error 
and recurses
-/// only through the installed vtable, preserving the input's mutation 
permission.
+/// only through the installed vtable, preserving the input's in-place mode.
 /// No whole-base mutable reference may span recursion. Failures use the result
 /// carrier; panics must not cross native callbacks.
 pub unsafe trait StructuralMutatorBase: Sized {
@@ -158,7 +135,7 @@ pub unsafe trait StructuralMutatorBase: Sized {
     /// Native type registered for this complete base layout.
     fn type_index() -> i32;
 
-    /// Descend from a borrowed capability without dispatching that value 
again.
+    /// Descend from a borrowed view without dispatching that value again.
     ///
     /// # Safety
     /// `runtime` is the base of a live `StructuralMutateEngine<Self>` with its
@@ -177,17 +154,8 @@ unsafe impl StructuralMutatorBase for StructuralMutatorObj 
{
     }
 
     fn type_index() -> i32 {
-        static TYPE_INDEX: ColdInitLazyLock<i32> = ColdInitLazyLock::new(|| 
unsafe {
-            let key = 
TVMFFIByteArray::from_str(StructuralMutatorObj::TYPE_KEY);
-            let mut type_index = 0;
-            if TVMFFITypeKeyToIndex(&key, &mut type_index) != 0 {
-                panic!(
-                    "ffi.StructuralMutator is not registered: {}",
-                    Error::from_raised()
-                );
-            }
-            type_index
-        });
+        static TYPE_INDEX: ColdInitLazyLock<i32> =
+            ColdInitLazyLock::new(|| 
registered_type_index(StructuralMutatorObj::TYPE_KEY));
         *TYPE_INDEX
     }
 
@@ -199,7 +167,7 @@ unsafe impl StructuralMutatorBase for StructuralMutatorObj {
         if let Some(attr) = Self::structural_mutate_hook(raw, value.mode) {
             return Self::call_structural_mutate_hook_raw(runtime, raw, attr);
         }
-        Self::mutate_without_hook_raw(runtime, raw.type_index, 
raw.small_str_len, raw.data_union)
+        Self::mutate_without_hook_raw(runtime, raw)
     }
 }
 
@@ -284,7 +252,7 @@ impl Drop for StructuralVarRemap {
 }
 
 impl<'source, 'value, T: crate::type_traits::ContainerElement>
-    
super::dispatch::DispatchRecovery<crate::match_any_internal::CapabilitySource<'source>>
+    
super::dispatch::DispatchRecovery<crate::match_any_internal::MutationSource<'source>>
     for crate::MutationView<'value, T>
 {
     type Recovery = crate::MutationView<'source>;
@@ -346,7 +314,7 @@ pub enum InplaceMode {
 }
 
 impl InplaceMode {
-    // Permission is only an upper bound; ownership must still be unique here.
+    // The mode is only an upper bound; ownership must still be unique here.
     #[inline(always)]
     fn for_value(self, raw: TVMFFIAny) -> Self {
         if self == Self::Allow && object_is_unique(raw) {
@@ -369,63 +337,15 @@ impl InplaceMode {
 /// `T` is the matched type: `MutationView<'_, Array<Any>>` derefs to the
 /// array's node, and the default `MutationView<'_>` matches every value. The
 /// view is move-only: it cannot be copied or cloned, and consuming it passes
-/// on the same permission. A view made from `&mut Any` may reuse storage;
+/// on the same mode. A view made from `&mut Any` may reuse storage;
 /// one made with [`borrowed`](MutationView::borrowed) never does.
 ///
 /// See also [`structural_mutate`].
-///
-/// A node borrowed through a copied view cannot survive consumption of the 
handle:
-/// ```compile_fail,E0505
-/// use tvm_ffi::{StructuralMutatorView, MutationView};
-/// fn invalid<D>(value: MutationView<'_>, dispatch: &mut D, mutator: &mut 
StructuralMutatorView<'_, D>) {
-///     let view = value.as_any_view();
-///     let copy = view;
-///     let node = 
copy.downcast_ref::<tvm_ffi::collections::array::ArrayObj>().unwrap();
-///     mutator.default_mutate(dispatch, value).unwrap();
-///     println!("{}", node.size);
-/// }
-/// ```
-///
-/// Moving the handle into a nested callback cannot bypass that borrow:
-/// ```compile_fail,E0505
-/// use tvm_ffi::{dispatch, structural_mutate, Any, MutationView, 
StructuralMutatorView, Result, UnchangedOr};
-/// struct Inner<'a>(Option<MutationView<'a>>);
-/// #[dispatch(mutate, (MutationView<'_>, &mut StructuralMutatorView<'_, 
Self>), Result<UnchangedOr<Any>>)]
-/// impl<'a> Inner<'a> {
-///     fn mutate_bool(&mut self, _: bool, mutator: &mut 
StructuralMutatorView<'_, Self>) -> Result<UnchangedOr<Any>> {
-///         let pending = self.0.take().unwrap();
-///         mutator.default_mutate(self, pending)
-///     }
-/// }
-/// fn invalid(value: MutationView<'_>) {
-///     let view = value.as_any_view();
-///     let node = 
view.downcast_ref::<tvm_ffi::collections::array::ArrayObj>().unwrap();
-///     structural_mutate(true, Inner(Some(value))).unwrap();
-///     println!("{}", node.size);
-/// }
-/// ```
-///
-/// A copied inspection view also cannot survive low-level default mutation:
-/// ```compile_fail,E0505
-/// use tvm_ffi::{dispatch, Any, MutationView, StructuralMutatorView, Result, 
Unchanged, UnchangedOr};
-/// struct Pass;
-/// #[dispatch(mutate, (MutationView<'_>, &mut StructuralMutatorView<'_, 
Self>), Result<UnchangedOr<Any>>)]
-/// impl Pass {
-///     fn mutate_any(&mut self, value: MutationView<'_>, mutator: &mut 
StructuralMutatorView<'_, Self>) -> Result<UnchangedOr<Any>> {
-///         let view = value.as_any_view();
-///         let copy = view;
-///         mutator.default_mutate(self, value).unwrap();
-///         println!("{}", copy.type_index());
-///         Ok(Unchanged.into())
-///     }
-/// }
-/// ```
 pub struct MutationView<'a, T = Any> {
     value: TVMFFIAny,
     mode: InplaceMode,
-    _scope: PhantomData<AnyView<'a>>,
-    _type: PhantomData<fn() -> T>,
-    _not_send_sync: PhantomData<Rc<()>>,
+    #[allow(clippy::type_complexity)]
+    _marker: PhantomData<(AnyView<'a>, fn() -> T, Rc<()>)>,
 }
 
 impl<T> MutationView<'_, T> {
@@ -439,13 +359,7 @@ impl<T> MutationView<'_, T> {
 impl<'a> MutationView<'a> {
     #[inline(always)]
     pub(super) fn new(value: AnyView<'a>, mode: InplaceMode) -> Self {
-        Self {
-            value: *value.as_raw_ffi_any(),
-            mode,
-            _scope: PhantomData,
-            _type: PhantomData,
-            _not_send_sync: PhantomData,
-        }
+        Self::from_raw(*value.as_raw_ffi_any(), mode)
     }
 
     /// Create a view of a borrowed value that never reuses its storage.
@@ -477,20 +391,23 @@ impl<'a> From<&'a mut Any> for MutationView<'a> {
 }
 
 impl<'a, T> MutationView<'a, T> {
-    // A chain may lend its capability to one link at a time. The shorter 
lifetime
+    #[inline(always)]
+    fn from_raw(value: TVMFFIAny, mode: InplaceMode) -> Self {
+        Self {
+            value,
+            mode,
+            _marker: PhantomData,
+        }
+    }
+
+    // A chain may lend its view to one link at a time. The shorter lifetime
     // prevents a matched link from retaining a borrow across the next link.
     #[inline(always)]
     pub(crate) fn reborrow(&mut self) -> MutationView<'_, T> {
-        MutationView {
-            value: self.value,
-            mode: self.mode,
-            _scope: PhantomData,
-            _type: PhantomData,
-            _not_send_sync: PhantomData,
-        }
+        MutationView::from_raw(self.value, self.mode)
     }
 
-    /// Return the permission this view carries.
+    /// Return the in-place mode this view carries.
     ///
     /// # Returns
     ///
@@ -500,18 +417,18 @@ impl<'a, T> MutationView<'a, T> {
         self.mode
     }
 
-    /// Restrict the permission, without ever upgrading it.
+    /// Restrict the mode, without ever upgrading it.
     ///
     /// `Disallow` turns off reuse. `Allow` keeps the current mode, so it never
     /// grants reuse to a view that does not have it, such as a borrowed one.
     ///
     /// # Arguments
     ///
-    /// * `requested` - The permission to restrict to.
+    /// * `requested` - The mode to restrict to.
     ///
     /// # Returns
     ///
-    /// The view with the restricted permission.
+    /// The view with the restricted mode.
     #[inline(always)]
     pub fn with_inplace_mode(mut self, requested: InplaceMode) -> Self {
         if requested == InplaceMode::Disallow {
@@ -530,12 +447,12 @@ impl<'a, T> MutationView<'a, T> {
     /// The value as an [`AnyView`].
     #[inline(always)]
     pub fn as_any_view(&self) -> AnyView<'_> {
-        // SAFETY: the input owner keeps this payload live while the 
capability is
+        // SAFETY: the input owner keeps this payload live while the view is
         // borrowed. The returned lifetime is bounded by self, not by 'a.
         unsafe { AnyView::from_raw_ffi_any(self.value) }
     }
 
-    /// Borrow the value as `U` without changing ownership or permission.
+    /// Borrow the value as `U` without changing ownership or mode.
     ///
     /// `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
@@ -555,7 +472,7 @@ impl<'a, T> MutationView<'a, T> {
     /// Narrow the matched type without acquiring an owning reference.
     ///
     /// The check is the strict one of [`Any::downcast_ref`], and the view 
keeps its
-    /// permission.
+    /// mode.
     ///
     /// # Returns
     ///
@@ -572,32 +489,20 @@ impl<'a, T> MutationView<'a, T> {
         // SAFETY: the input owner keeps the borrowed value live for this 
handle's
         // lifetime. This only checks its type and does not acquire ownership.
         if unsafe { U::container_check_any_strict(&self.value) } {
-            Ok(MutationView {
-                value: self.value,
-                mode: self.mode,
-                _scope: PhantomData,
-                _type: PhantomData,
-                _not_send_sync: PhantomData,
-            })
+            Ok(MutationView::from_raw(self.value, self.mode))
         } else {
             Err(self)
         }
     }
 
-    /// Erase the matched type while preserving the carried permission.
+    /// Erase the matched type while preserving the carried mode.
     ///
     /// # Returns
     ///
     /// The view as `MutationView<'_>`.
     #[inline(always)]
     pub fn into_untyped(self) -> MutationView<'a> {
-        MutationView {
-            value: self.value,
-            mode: self.mode,
-            _scope: PhantomData,
-            _type: PhantomData,
-            _not_send_sync: PhantomData,
-        }
+        MutationView::from_raw(self.value, self.mode)
     }
 }
 
@@ -619,7 +524,7 @@ impl<T: object::ObjectRefCore> std::ops::Deref for 
MutationView<'_, T> {
 
     #[inline(always)]
     fn deref(&self) -> &Self::Target {
-        // SAFETY: typed capability construction establishes T's object layout;
+        // SAFETY: typed view construction establishes T's object layout;
         // this shared borrow cannot outlive or survive consumption of the 
handle.
         unsafe { &*self.value.data_union.v_obj.cast::<T::ContainerType>() }
     }
@@ -687,17 +592,11 @@ impl<T: object::ObjectRefCore> MutationView<'_, T> {
         );
         let mut value = TVMFFIAny::new();
         // SAFETY: child is a live owning field. Copying its view acquires no 
owner;
-        // the returned capability exclusively borrows the parent capability.
+        // the returned view exclusively borrows the parent view.
         unsafe { U::container_copy_to_any_view(child, &mut value) };
         // Selection and conversion may retain aliases, so check the parent 
last.
         let mode = self.mode.for_value(self.value);
-        MutationView {
-            value,
-            mode,
-            _scope: PhantomData,
-            _type: PhantomData,
-            _not_send_sync: PhantomData,
-        }
+        MutationView::from_raw(value, mode)
     }
 }
 
@@ -712,9 +611,8 @@ impl<T: object::ObjectRefCore> MutationView<'_, T> {
 /// See also [`structural_mutate`].
 pub struct StructuralMutatorView<'a, D, Base = StructuralMutatorObj> {
     runtime: StructuralMutatorHandle,
-    _scope: PhantomData<&'a mut ()>,
-    _dispatcher: PhantomData<fn(&mut D) -> Base>,
-    _not_send_sync: PhantomData<Rc<()>>,
+    #[allow(clippy::type_complexity)]
+    _marker: PhantomData<(&'a mut (), fn(&mut D) -> Base, Rc<()>)>,
 }
 
 impl<D, Base: StructuralMutatorBase> StructuralMutatorView<'_, D, Base> {
@@ -734,9 +632,7 @@ impl<D, Base: StructuralMutatorBase> 
StructuralMutatorView<'_, D, Base> {
     fn reborrow(&self) -> StructuralMutatorView<'_, D, Base> {
         StructuralMutatorView {
             runtime: self.runtime,
-            _scope: PhantomData,
-            _dispatcher: PhantomData,
-            _not_send_sync: PhantomData,
+            _marker: PhantomData,
         }
     }
 
@@ -750,6 +646,7 @@ impl<D, Base: StructuralMutatorBase> 
StructuralMutatorView<'_, D, Base> {
     /// The current definition region.
     #[inline(always)]
     pub fn def_region_kind(&self) -> DefRegionKind {
+        // SAFETY: the view's runtime is live.
         unsafe { std::mem::transmute(*(*self.runtime).def_region_mode.get()) }
     }
 
@@ -773,6 +670,7 @@ impl<D, Base: StructuralMutatorBase> 
StructuralMutatorView<'_, D, Base> {
         kind: DefRegionKind,
         callback: impl FnOnce(&mut StructuralMutatorView<'_, D, Base>) -> R,
     ) -> R {
+        // SAFETY: the view's runtime outlives the callback.
         StructuralMutatorObj::with_def_region_kind(self.runtime, kind, |_| {
             callback(&mut self.reborrow())
         })
@@ -780,7 +678,7 @@ impl<D, Base: StructuralMutatorBase> 
StructuralMutatorView<'_, D, Base> {
 
     /// Mutate `value` through the dispatcher, as if the traversal had reached 
it.
     ///
-    /// `value` keeps the permission it carries. Use it to rewrite a value 
other
+    /// `value` keeps the mode it carries. Use it to rewrite a value other
     /// than the current node, such as a field selected with
     /// [`MutationView::field`].
     ///
@@ -843,7 +741,7 @@ impl<D, Base: StructuralMutatorBase> 
StructuralMutatorView<'_, D, Base> {
         unsafe {
             let context =
                 
StructuralMutateEngine::<Base>::checked_dispatcher(self.runtime, dispatch);
-            
raw_ffi_any_into_result(StructuralMutateEngine::<Base>::default_mutate_raw(
+            
raw_ffi_any_into_result(StructuralMutateEngine::<Base>::publish_and_descend_raw(
                 self.runtime,
                 context,
                 value.value,
@@ -913,10 +811,7 @@ impl<D, Base: StructuralMutatorBase> 
StructuralMutatorView<'_, D, Base> {
 }
 
 impl<Base: StructuralMutatorBase> StructuralMutateEngine<Base> {
-    /// Normalize the input once and traverse using this engine's native base.
-    /// Named dispatchers keep their actual recursive view type. Callback and
-    /// tuple targets are their aggregate adapters; closures taking their own
-    /// recursive view type remain unsupported.
+    /// Mutate `root` with `dispatcher` on the native base `Base`. See also 
[`structural_mutate`].
     #[inline(always)]
     pub fn mutate_root<R, H, M, D, O>(root: R, dispatcher: H) -> Result<Any>
     where
@@ -934,6 +829,8 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
             Option<Result<UnchangedOr<Any>>>,
         >,
     {
+        // Normalize the input once. Named dispatchers keep their own 
recursive view
+        // type; callback and tuple targets are their aggregate adapters.
         let mut storage = dispatcher.into_dispatcher();
         Self::run_mutator::<D, true>(root.into(), storage.borrow_mut())
     }
@@ -942,7 +839,6 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
 // 
-----------------------------------------------------------------------------
 // Outlined errors
 // 
-----------------------------------------------------------------------------
-// Keep construction and formatting scratch outside successful traversal 
frames.
 
 #[cold]
 #[inline(never)]
@@ -1023,20 +919,13 @@ fn unregistered_type_error(type_index: i32) -> Error {
     ))
 }
 
-// Keep panic construction out of the successful dispatcher identity check.
-#[cold]
-#[inline(never)]
-fn wrong_mutation_dispatcher() -> ! {
-    panic!("mutation context used with a different dispatcher instance")
-}
-
 #[cold]
 pub(super) fn with_mutation_error_context(error: Error, raw: TVMFFIAny, 
operation: &str) -> Error {
     if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
         error
     } else {
         with_structural_error_context(
-            with_visit_error_context(error, raw),
+            update_visit_error_context(error, raw),
             operation,
             &format!(
                 "object `{}`",
@@ -1228,16 +1117,12 @@ static SHALLOW_COPY_COLUMN: 
ColdInitLazyLock<TypeAttrColumn> = ColdInitLazyLock:
 // Raw bits provide no ownership guard: import an owning result into Any before
 // fallible work or destruction of an observer; borrowed inputs must stay live.
 impl<Base: StructuralMutatorBase> StructuralMutateEngine<Base> {
-    /// Recover the engine prefix for internal runtime projections.
+    /// The engine whose first field is the native prefix `runtime`.
     ///
     /// # Safety
-    /// `runtime` must be this live Rust engine, not an arbitrary native 
mutator.
-    /// The returned pointer borrows it; no whole-engine reference may span 
recursion.
-    // Unsafe internals preserve a safe API: the matching runtime and 
dispatcher
-    // remain live for this synchronous call, and each recursive entry 
publishes
-    // its actual exclusive reborrow. No whole-engine reference spans 
recursion.
-    // Callbacks use Result for failures and must not unwind across the C ABI.
-    // The live handle starts this exact Rust engine; only raw projections 
cross recursion.
+    ///
+    /// `runtime` is this live Rust engine, not an arbitrary native mutator; 
only raw
+    /// projections of the result may cross recursion.
     #[inline(always)]
     unsafe fn from_handle(runtime: StructuralMutatorHandle) -> *mut Self {
         runtime.cast()
@@ -1256,7 +1141,7 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
         let context = std::ptr::from_mut(dispatch).cast();
         if context != (*Self::from_handle(runtime)).dispatcher {
             core::hint::cold_path();
-            wrong_mutation_dispatcher();
+            wrong_dispatcher();
         }
         context
     }
@@ -1280,7 +1165,7 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
     }
 
     /// Enter a native callback with borrowed `value` and return one owning 
raw result.
-    /// `INPLACE` grants permission only; uniqueness is checked before 
dispatch.
+    /// `INPLACE` sets the mode only; uniqueness is checked before dispatch.
     ///
     /// # Safety
     /// `runtime` must have this `D` vtable and a live published exclusive 
reborrow.
@@ -1307,9 +1192,7 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
         let dispatch = &mut *context.cast::<D>();
         let mut mutator = StructuralMutatorView {
             runtime,
-            _scope: PhantomData,
-            _dispatcher: PhantomData,
-            _not_send_sync: PhantomData,
+            _marker: PhantomData,
         };
         let result = match Dispatcher::dispatch_tuple(
             &mut *dispatch,
@@ -1325,9 +1208,12 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
                     result
                 })
             }
-            None => {
-                Self::default_mutate_raw(runtime, 
std::ptr::from_mut(dispatch).cast(), raw, mode)
-            }
+            None => Self::publish_and_descend_raw(
+                runtime,
+                std::ptr::from_mut(dispatch).cast(),
+                raw,
+                mode,
+            ),
         };
         // All callback reborrows have ended before restoring the caller's 
provenance.
         (*Self::from_handle(runtime)).dispatcher = context;
@@ -1335,13 +1221,13 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
     }
 
     /// Publish `context`, then descend through hooks or reflection for 
borrowed `raw`.
-    /// `mode` grants reuse permission, not proof of uniqueness. Returns one 
owning token.
+    /// `mode` is an upper bound, not proof of uniqueness. Returns one owning 
token.
     ///
     /// # Safety
     /// `runtime` must be live; `context` must be its current exclusive 
dispatcher
     /// reborrow, and `raw` must remain valid throughout synchronous descent.
     #[inline(always)]
-    unsafe fn default_mutate_raw(
+    unsafe fn publish_and_descend_raw(
         runtime: StructuralMutatorHandle,
         context: *mut c_void,
         raw: TVMFFIAny,
@@ -1452,94 +1338,60 @@ impl<Base: StructuralMutatorBase> 
StructuralMutateEngine<Base> {
                 type_index,
             )
         };
-        let handle = ObjectArc::as_mut_ptr(&mut 
engine).cast::<StructuralMutatorObj>();
-        unsafe { (*handle).vtable = Self::vtable::<D, CALLBACK_CONTEXT>() };
+        let runtime = ObjectArc::as_mut_ptr(&mut 
engine).cast::<StructuralMutatorObj>();
+        unsafe { (*runtime).vtable = Self::vtable::<D, CALLBACK_CONTEXT>() };
         let result =
-            StructuralMutatorObj::call_mutator(handle, *root.as_raw_ffi_any(), 
InplaceMode::Allow);
+            StructuralMutatorObj::call_mutator(runtime, 
*root.as_raw_ffi_any(), InplaceMode::Allow);
         // Native hooks release temporary runtime owners before this 
synchronous run ends.
         drop(engine);
         result.map(|value| if is_unchanged(&value) { root } else { value })
     }
 }
 
-// Public prefix helpers use only the native layout and installed vtable.
+// Prefix operations use only the native layout and installed vtable.
 impl StructuralMutatorObj {
-    /// Consume the native hook owning `result`, annotating errors with 
borrowed `raw`.
-    /// Nonerrors transfer unchanged; packed successful Error values do not 
use this path.
+    /// Consume a native hook's `result`, naming the borrowed `raw` in it when 
it is an Error.
     ///
     /// # Safety
-    /// `result` must own one valid ABI value and `raw` must remain live 
during annotation.
+    ///
+    /// `result` owns one valid value and `raw` outlives the call.
     #[inline(always)]
     unsafe fn with_native_mutation_context_raw(result: TVMFFIAny, raw: 
TVMFFIAny) -> TVMFFIAny {
         if result.type_index != TVMFFITypeIndex::kTVMFFIError as i32 {
             result
         } else {
             core::hint::cold_path();
-            Self::with_mutation_context_raw(
-                result.type_index,
-                result.small_str_len,
-                result.data_union,
-                raw.type_index,
-                raw.small_str_len,
-                raw.data_union,
-            )
+            Self::with_mutation_context_raw(result, raw)
         }
     }
 
-    /// Reconstruct an owning error from `result_*` and borrowed input from 
the other
-    /// scalar fields, then transfer one context-annotated owning raw result.
-    /// This private C-unwind helper uses AArch64 register returns and permits 
Rust
-    /// cleanup on unwind; it changes no public or native callback ABI.
+    /// The cold arm of [`Self::with_native_mutation_context_raw`].
     ///
     /// # Safety
-    /// The result fields must describe one owned Error; the input fields must 
describe
-    /// a live borrowed value. No caller may release the transferred error 
token.
-    // Outline error annotation scratch; the AArch64 C ABI returns the raw
-    // carrier in registers while C-unwind preserves Rust cleanup on panic.
+    ///
+    /// `result` owns one Error, and `raw` is a live borrowed value.
     #[cold]
     #[inline(never)]
     unsafe extern "C-unwind" fn with_mutation_context_raw(
-        result_type_index: i32,
-        result_small_str_len: u32,
-        result_data: TVMFFIAnyDataUnion,
-        type_index: i32,
-        small_str_len: u32,
-        data_union: TVMFFIAnyDataUnion,
+        result: TVMFFIAny,
+        raw: TVMFFIAny,
     ) -> TVMFFIAny {
-        let result = TVMFFIAny {
-            type_index: result_type_index,
-            small_str_len: result_small_str_len,
-            data_union: result_data,
-        };
-        let raw = TVMFFIAny {
-            type_index,
-            small_str_len,
-            data_union,
-        };
         result_into_raw_ffi_any(
             raw_ffi_any_into_result(result)
                 .map_err(|error| with_mutation_error_context(error, raw, 
"mutate")),
         )
     }
 
-    /// Map registered fields of borrowed `raw` using live `runtime` and 
`type_info`.
-    /// `def_region_kind` is the fallback-entry snapshot. Own the shallow copy 
and
-    /// getter results through recursion/setters; return a replacement or 
Unchanged.
-    /// Internal callers provide valid registered metadata and a live input 
owner.
+    /// Mutate the reflected fields of a shallow copy of borrowed `raw`; 
`Unchanged` when no
+    /// field changed.
     fn map_reflected(
         runtime: StructuralMutatorHandle,
         raw: TVMFFIAny,
         def_region_kind: DefRegionKind,
         type_info: *const crate::tvm_ffi_sys::TVMFFITypeInfo,
     ) -> Result<Any> {
-        let seq_hash_kind = unsafe {
-            if (*type_info).metadata.is_null() {
-                TVMFFISEqHashKind::kTVMFFISEqHashKindUnsupported as i32
-            } else {
-                (*(*type_info).metadata).structural_eq_hash_kind
-            }
-        };
-        let inherited_region = free_var_child_region(def_region_kind, 
seq_hash_kind);
+        let inherited_region =
+            free_var_child_region(def_region_kind, unsafe { 
seq_hash_kind(type_info) });
         // Match the C++ reflected-mutation contract: resolve and invoke the
         // shallow-copy hook before inspecting any fields. Besides providing
         // isolated setter storage, this means a missing or failing hook is an
@@ -1585,13 +1437,12 @@ impl StructuralMutatorObj {
         }
     }
 
-    /// Map one field of the owned shallow copy and set `field_changed` on 
replacement.
-    /// `inherited_region` supplies the parent definition policy. 
Getter/result owners
-    /// survive recursion and setters; errors retain field context.
+    /// Mutate one reflected `field` of `output_object`, setting 
`field_changed` on a
+    /// replacement.
     ///
     /// # Safety
-    /// `runtime` must be live; `output_object` and registered `field` 
metadata must
-    /// describe a valid live copy, including its getter/setter offsets and 
ABIs.
+    ///
+    /// `runtime` is live, and `field` describes `output_object`'s storage.
     unsafe fn map_reflected_field(
         runtime: StructuralMutatorHandle,
         output_object: *mut u8,
@@ -1644,36 +1495,32 @@ impl StructuralMutatorObj {
         Ok(())
     }
 
-    /// Invoke a live mutator vtable on borrowed `raw` and import its owning 
result.
-    /// Internal callers keep both live; `mode` permits reuse only after a 
fresh
-    /// uniqueness check. Native callbacks cannot unwind through their C ABI.
+    /// Dispatch borrowed `raw` through the runtime's vtable, in place when 
`mode` allows
+    /// it and `raw` is unique.
     #[inline(always)]
     fn call_mutator(
-        mutator: StructuralMutatorHandle,
+        runtime: StructuralMutatorHandle,
         raw: TVMFFIAny,
         mode: InplaceMode,
     ) -> Result<Any> {
-        let use_inplace = mode == InplaceMode::Allow && object_is_unique(raw);
         let callback = unsafe {
-            if use_inplace {
-                (*(*mutator).vtable).maybe_inplace_mutate
+            if mode.for_value(raw) == InplaceMode::Allow {
+                (*(*runtime).vtable).maybe_inplace_mutate
             } else {
-                (*(*mutator).vtable).mutate
+                (*(*runtime).vtable).mutate
             }
         };
         unsafe {
             let view = AnyView::from_raw_ffi_any(raw);
-            raw_ffi_any_into_result(callback(mutator, view))
+            raw_ffi_any_into_result(callback(runtime, view))
         }
     }
 
-    /// Borrow the registered hook cell for live `raw`. Recheck uniqueness for
-    /// `mode` before selecting an in-place hook, otherwise use the normal 
column.
-    /// The registry owns the returned attribute; no reference count is 
acquired.
+    /// The registered mutation hook of `raw`: the in-place one when `mode` 
allows it and
+    /// `raw` is unique, otherwise the copying one.
     #[inline(always)]
     fn structural_mutate_hook(raw: TVMFFIAny, mode: InplaceMode) -> 
Option<TVMFFIAny> {
-        let use_inplace = mode == InplaceMode::Allow && object_is_unique(raw);
-        if use_inplace {
+        if mode.for_value(raw) == InplaceMode::Allow {
             if let Some(attr) = 
structural_mutate_column::<true>().get_raw_ffi_any(raw.type_index) {
                 if attr.type_index == TVMFFITypeIndex::kTVMFFIOpaquePtr as i32
                     || attr.type_index == TVMFFITypeIndex::kTVMFFIFunction as 
i32
@@ -1686,18 +1533,17 @@ impl StructuralMutatorObj {
         (attr.type_index != TVMFFITypeIndex::kTVMFFINone as 
i32).then_some(attr)
     }
 
-    /// Invoke a native or packed hook with borrowed `mutator`, `value` and 
`hook`.
-    /// Return one owning result; native Error results receive input context.
+    /// Call the registered mutation `hook` (native pointer or packed 
function) on `value`.
     ///
     /// # Safety
-    /// The runtime and inputs must remain live for this synchronous call. 
Publish
-    /// the current exclusive dispatcher reborrow first. A native hook must be 
a
-    /// non-null function with the mutation ABI accepting this complete runtime
-    /// layout. All hooks obey [`StructuralMutatorBase`]'s non-escaping 
contract.
-    /// The caller must have permission for any in-place mutation the hook 
performs.
+    ///
+    /// `runtime` is live with its dispatcher published, `value` and `hook` 
outlive the call,
+    /// the caller's mode allows any in-place mutation the hook performs, and 
a native hook
+    /// has the mutation ABI for this runtime's layout and obeys 
[`StructuralMutatorBase`]'s
+    /// non-escaping contract.
     #[inline(always)]
     pub unsafe fn call_structural_mutate_hook_raw(
-        mutator: *mut Self,
+        runtime: *mut Self,
         value: TVMFFIAny,
         hook: TVMFFIAny,
     ) -> TVMFFIAny {
@@ -1705,59 +1551,31 @@ impl StructuralMutatorObj {
             if hook.type_index == TVMFFITypeIndex::kTVMFFIOpaquePtr as i32 {
                 let callback: FStructuralMutate = 
std::mem::transmute(hook.data_union.v_ptr);
                 Self::with_native_mutation_context_raw(
-                    callback(mutator, AnyView::from_raw_ffi_any(value)),
+                    callback(runtime, AnyView::from_raw_ffi_any(value)),
                     value,
                 )
             } else {
-                Self::call_structural_mutate_hook_slow_raw(
-                    mutator,
-                    value.type_index,
-                    value.small_str_len,
-                    value.data_union,
-                    hook.type_index,
-                    hook.small_str_len,
-                    hook.data_union,
-                )
+                Self::call_structural_mutate_hook_slow_raw(runtime, value, 
hook)
             }
         }
     }
 
-    /// Reconstruct borrowed input and attribute from their scalar fields for 
the
-    /// packed/malformed-hook fallback. `mutator` is borrowed for the call. 
Return
-    /// one owning token after Function/argument cleanup; annotate actual Err 
only.
-    /// The private C-unwind ABI preserves Rust cleanup and AArch64 register 
returns
-    /// without changing public or native callback ABIs.
+    /// The packed-function arm of [`Self::call_structural_mutate_hook_raw`], 
outlined as cold.
     ///
     /// # Safety
-    /// `mutator`, input fields, and registered attribute fields must remain 
valid
-    /// through this synchronous call; none of these inputs transfers 
ownership.
-    // Outline packed-call scratch; the AArch64 C ABI keeps raw results in
-    // registers while C-unwind preserves Rust cleanup inside this private 
tail.
+    ///
+    /// As [`Self::call_structural_mutate_hook_raw`].
     #[cold]
     #[inline(never)]
     unsafe extern "C-unwind" fn call_structural_mutate_hook_slow_raw(
-        mutator: StructuralMutatorHandle,
-        type_index: i32,
-        small_str_len: u32,
-        data_union: TVMFFIAnyDataUnion,
-        attr_type_index: i32,
-        attr_small_str_len: u32,
-        attr_data_union: TVMFFIAnyDataUnion,
+        runtime: StructuralMutatorHandle,
+        raw: TVMFFIAny,
+        attr: TVMFFIAny,
     ) -> TVMFFIAny {
-        let raw = TVMFFIAny {
-            type_index,
-            small_str_len,
-            data_union,
-        };
-        let attr = TVMFFIAny {
-            type_index: attr_type_index,
-            small_str_len: attr_small_str_len,
-            data_union: attr_data_union,
-        };
         let result = if attr.type_index == TVMFFITypeIndex::kTVMFFIFunction as 
i32 {
             
Function::try_from(AnyView::from_raw_ffi_any(attr)).and_then(|function| {
                 function.call_packed(&[
-                    Self::borrowed_mutator_view(mutator),
+                    Self::borrowed_mutator_view(runtime),
                     AnyView::from_raw_ffi_any(raw),
                 ])
             })
@@ -1770,15 +1588,14 @@ impl StructuralMutatorObj {
         )
     }
 
-    /// Borrow a live runtime mutator as an object-valued ABI argument.
+    /// Borrow the live `runtime` as an object argument, without a reference 
count.
     ///
     /// # Safety
     ///
-    /// `mutator` must point to a live object and outlive the returned view. 
The
-    /// view does not increment the object's reference count.
+    /// `runtime` outlives the returned view.
     #[inline(always)]
-    unsafe fn borrowed_mutator_view<'a>(mutator: StructuralMutatorHandle) -> 
AnyView<'a> {
-        let object = mutator.cast::<TVMFFIObject>();
+    unsafe fn borrowed_mutator_view<'a>(runtime: StructuralMutatorHandle) -> 
AnyView<'a> {
+        let object = runtime.cast::<TVMFFIObject>();
         let mut raw = TVMFFIAny::new();
         raw.type_index = (*object).type_index;
         raw.small_str_len = 0;
@@ -1819,34 +1636,21 @@ impl StructuralMutatorObj {
         }
     }
 
-    /// Snapshot the live `runtime` region before fallback work, reconstruct 
borrowed
-    /// input from scalar fields, and transfer one owning 
replacement/Unchanged/Error.
-    /// The private C-unwind ABI keeps AArch64 results in registers while 
permitting
-    /// Rust cleanup; public/native callback ABIs remain unchanged.
+    /// Mutate borrowed `raw` by reflection, caching free variables and DAG 
nodes
+    /// through the vtable remap.
     ///
     /// # Safety
-    /// `runtime` must be a live mutator prefix and the input fields a valid 
borrowed value.
-    /// The input owner must survive reflection, remap updates, and error 
annotation.
-    // Perf note: Keep reflection scratch outside recursive frames. This 
fallback
-    // can be frequent, so inline(never) is intentional without cold.
-    // The AArch64 C ABI keeps raw results in registers; C-unwind preserves
-    // Rust unwinding inside this private helper.
+    ///
+    /// `runtime` is a live mutator prefix with its vtable, and `raw` outlives 
the call.
+    /// Outlined (frequent, not cold) to keep reflection scratch out of 
recursive frames.
     #[inline(never)]
     unsafe extern "C-unwind" fn mutate_without_hook_raw(
         runtime: StructuralMutatorHandle,
-        type_index: i32,
-        small_str_len: u32,
-        data_union: TVMFFIAnyDataUnion,
+        raw: TVMFFIAny,
     ) -> TVMFFIAny {
-        // Perf note: Read region state here, before fallback semantics need 
it,
-        // rather than loading it on the native-hook path that does not use it.
+        // Read the region here rather than on the native-hook path, which 
does not use it.
         let def_region_kind =
             std::mem::transmute::<i32, 
DefRegionKind>(*(*runtime).def_region_mode.get());
-        let raw = TVMFFIAny {
-            type_index,
-            small_str_len,
-            data_union,
-        };
         result_into_raw_ffi_any(
             Self::mutate_without_hook(runtime, raw, def_region_kind)
                 .map_err(|error| with_mutation_error_context(error, raw, 
"mutate")),
@@ -1882,10 +1686,7 @@ impl StructuralMutatorObj {
         .map(|_| ())
     }
 
-    /// Resolve fallback mutation for live borrowed `raw` and `runtime`, using 
the
-    /// entry snapshot `def_region_kind`. Preserve cached identities, 
free-variable
-    /// policy and owning reflected results. Internal callers guarantee valid 
inputs;
-    /// normal Rust owners clean up partial work if reflection fails or 
unwinds.
+    /// The reflective mutation of [`Self::mutate_without_hook_raw`], on owned 
results.
     #[inline(always)]
     fn mutate_without_hook(
         runtime: StructuralMutatorHandle,
@@ -1897,15 +1698,9 @@ impl StructuralMutatorObj {
         }
 
         let type_info = checked_type_info(raw.type_index)?;
-        let kind = unsafe {
-            if (*type_info).metadata.is_null() {
-                None
-            } else {
-                Some((*(*type_info).metadata).structural_eq_hash_kind)
-            }
-        };
-        let is_free_var = kind == 
Some(TVMFFISEqHashKind::kTVMFFISEqHashKindFreeVar as i32);
-        let is_dag_node = kind == 
Some(TVMFFISEqHashKind::kTVMFFISEqHashKindDAGNode as i32);
+        let kind = unsafe { seq_hash_kind(type_info) };
+        let is_free_var = kind == TVMFFISEqHashKind::kTVMFFISEqHashKindFreeVar 
as i32;
+        let is_dag_node = kind == TVMFFISEqHashKind::kTVMFFISEqHashKindDAGNode 
as i32;
         if is_free_var || is_dag_node {
             // The ABI uses None for a miss; an Unchanged marker is a cached 
result.
             if let Some(mutated) = unsafe { Self::var_remap_get(runtime, raw)? 
} {
diff --git a/rust/tvm-ffi/src/extra/structural_visit.rs 
b/rust/tvm-ffi/src/extra/structural_visit.rs
index 7ca70d05..38e96019 100644
--- a/rust/tvm-ffi/src/extra/structural_visit.rs
+++ b/rust/tvm-ffi/src/extra/structural_visit.rs
@@ -46,26 +46,8 @@
 //! reaching the non-unwinding `extern "C"` callback boundary aborts the 
process;
 //! visitor callbacks do not catch or transport panic payloads across native 
frames.
 
-// 
-----------------------------------------------------------------------------
-// Implementation overview
-// 
-----------------------------------------------------------------------------
-//
-// This file is organized into:
-// - Data structures and visiting capabilities.
-// - Outlined errors and private utility functions.
-// - Engine implementation and the public entry point.
-//
-// We use narrowly scoped unsafe code for native interoperation and efficient
-// traversal. Safety and ownership contracts are documented at each boundary.
-//
-// The main performance strategies are:
-// - Outline cold work to keep its temporary storage out of recursive frames.
-// - Use _raw helpers and private extern "C-unwind" boundaries for register
-//   transport on AArch64 while preserving Rust unwinding.
-// - Inline small conversions and forwarding code so ownership transfers and
-//   redundant cleanup can optimize away.
-//
-// Local Perf note comments explain individual implementation choices.
+// `_raw` functions move one owned `TVMFFIAny`: forward it once, or import it 
into `Any` before
+// anything can unwind. Private `extern "C-unwind"` helpers return it in 
registers on AArch64.
 
 use std::cell::UnsafeCell;
 use std::marker::PhantomData;
@@ -85,24 +67,19 @@ use crate::error::{Error, Result, TYPE_ERROR};
 use crate::function::Function;
 use crate::object::{Object, ObjectArc};
 use crate::reflection::TypeAttrColumn;
-use crate::tvm_ffi_sys::TVMFFIFieldFlagBitMask::{
-    kTVMFFIFieldFlagBitMaskSEqHashDefPattern, 
kTVMFFIFieldFlagBitMaskSEqHashDefSimple,
-    kTVMFFIFieldFlagBitMaskSEqHashIgnore,
-};
 use crate::tvm_ffi_sys::{
-    TVMFFIAny, TVMFFIAnyDataUnion, TVMFFIByteArray, TVMFFIDefRegionKind, 
TVMFFIFieldInfo,
-    TVMFFIGetTypeInfo, TVMFFIObject, TVMFFISEqHashKind, TVMFFITypeIndex, 
TVMFFITypeKeyToIndex,
+    TVMFFIAny, TVMFFIDefRegionKind, TVMFFIFieldInfo, TVMFFIGetTypeInfo, 
TVMFFIObject,
+    TVMFFITypeIndex,
 };
 
 use super::structural_common::{
-    missing_field_getter_error, runtime_error, with_structural_error_context,
-    with_structural_field_error_context, with_visit_error_context,
+    field_def_region, for_each_field_info, free_var_child_region, 
missing_field_getter_error,
+    registered_type_index, runtime_error, seq_hash_kind, 
with_structural_error_context,
+    with_structural_field_error_context, wrong_dispatcher, 
FLAG_SEQ_HASH_IGNORE,
 };
+use super::visit_error_context::update_visit_error_context;
 
 const STRUCTURAL_VISIT_ATTR: &str = "__s_visit__";
-const FLAG_SEQ_HASH_IGNORE: i64 = kTVMFFIFieldFlagBitMaskSEqHashIgnore as i64;
-const FLAG_SEQ_HASH_DEF_PATTERN: i64 = 
kTVMFFIFieldFlagBitMaskSEqHashDefPattern as i64;
-const FLAG_SEQ_HASH_DEF_SIMPLE: i64 = kTVMFFIFieldFlagBitMaskSEqHashDefSimple 
as i64;
 
 // 
-----------------------------------------------------------------------------
 // Data structures and FFI layout
@@ -199,18 +176,8 @@ unsafe impl StructuralVisitorBase for StructuralVisitorObj 
{
     }
 
     fn type_index() -> i32 {
-        static TYPE_INDEX: ColdInitLazyLock<i32> = ColdInitLazyLock::new(|| 
unsafe {
-            let key = 
TVMFFIByteArray::from_str(StructuralVisitorObj::TYPE_KEY);
-            let mut type_index = 0;
-            let return_code = TVMFFITypeKeyToIndex(&key, &mut type_index);
-            if return_code != 0 {
-                panic!(
-                    "ffi.StructuralVisitor is not registered: {}",
-                    Error::from_raised()
-                );
-            }
-            type_index
-        });
+        static TYPE_INDEX: ColdInitLazyLock<i32> =
+            ColdInitLazyLock::new(|| 
registered_type_index(StructuralVisitorObj::TYPE_KEY));
         *TYPE_INDEX
     }
 
@@ -311,10 +278,6 @@ impl VisitInterrupt {
 // Public visitor API
 // 
-----------------------------------------------------------------------------
 
-// Internal visit protocol matches the C++ owning TVMFFIAny result: None means
-// continue; VisitInterrupt (including None/Error payloads) and Error stop 
descent.
-// Each ABI ingress/import and egress/export transfers ownership exactly once.
-// Recursive drivers move this carrier unchanged; typed public APIs decode it.
 /// The running structural visit, passed to each handler.
 ///
 /// A handler that matches a node decides which children are visited: call
@@ -328,33 +291,11 @@ impl VisitInterrupt {
 pub struct StructuralVisitorView<'a, D, Base = StructuralVisitorObj> {
     runtime: StructuralVisitorHandle,
     #[allow(clippy::type_complexity)]
-    _scope: PhantomData<(&'a mut (), fn(&mut D) -> Base, Rc<()>)>,
+    _marker: PhantomData<(&'a mut (), fn(&mut D) -> Base, Rc<()>)>,
 }
 
 impl<D, Base: StructuralVisitorBase> StructuralVisitorView<'_, D, Base> {
-    /// Inspect the base state without retaining the scoped visitor runtime.
-    ///
-    /// The reference cannot outlive its view:
-    ///
-    /// # Returns
-    ///
-    /// The base state, borrowed for the lifetime of this view.
-    ///
-    /// ```compile_fail
-    /// use tvm_ffi::{StructuralVisitorObj, StructuralVisitorView};
-    /// fn retain<D>(view: &StructuralVisitorView<'_, D>) -> &'static 
StructuralVisitorObj {
-    ///     view.base()
-    /// }
-    /// ```
-    ///
-    /// The prefix cannot be converted into an owning FFI value:
-    ///
-    /// ```compile_fail
-    /// use tvm_ffi::{Any, StructuralVisitorView};
-    /// fn retain<D>(view: &StructuralVisitorView<'_, D>) -> Any {
-    ///     Any::from(view.base())
-    /// }
-    /// ```
+    /// Inspect the base state; the borrow cannot outlive this view.
     #[inline(always)]
     pub fn base(&self) -> &Base {
         // SAFETY: the unsafe base contract permits shared inspection, 
including
@@ -372,7 +313,7 @@ impl<D, Base: StructuralVisitorBase> 
StructuralVisitorView<'_, D, Base> {
     /// The current definition region.
     #[inline(always)]
     pub fn def_region_kind(&self) -> DefRegionKind {
-        // SAFETY: engine scopes and trusted ABI hooks store valid enum values.
+        // SAFETY: the view's runtime is live.
         unsafe { std::mem::transmute(*(*self.runtime).def_region_mode.get()) }
     }
 
@@ -395,6 +336,7 @@ impl<D, Base: StructuralVisitorBase> 
StructuralVisitorView<'_, D, Base> {
         kind: DefRegionKind,
         callback: impl FnOnce(&mut Self) -> R,
     ) -> R {
+        // SAFETY: the view's runtime outlives the callback.
         StructuralVisitorObj::with_def_region_kind(self.runtime, kind, || 
callback(self))
     }
 
@@ -475,10 +417,7 @@ impl<D, Base: StructuralVisitorBase> 
StructuralVisitorView<'_, D, Base> {
 }
 
 impl<Base: StructuralVisitorBase> StructuralVisitEngine<Base> {
-    /// Normalize the input once and traverse using this engine's native base.
-    /// Named dispatchers keep their actual recursive view type. Callback and
-    /// tuple targets are their aggregate adapters; closures taking their own
-    /// recursive view type remain unsupported.
+    /// Visit `root` with `dispatcher` on the native base `Base`. See also 
[`structural_visit`].
     #[inline(always)]
     pub fn visit_root<'input, R, H, M, D, O>(
         root: R,
@@ -499,14 +438,11 @@ impl<Base: StructuralVisitorBase> 
StructuralVisitEngine<Base> {
             Option<Result<Option<VisitInterrupt>>>,
         >,
     {
+        // Normalize the input once. Named dispatchers keep their own 
recursive view
+        // type; callback and tuple targets are their aggregate adapters.
         let mut storage = dispatcher.into_dispatcher();
         let root = root.into();
-        visit_result_from_any(unsafe {
-            Any::from_raw_ffi_any(Self::run_visitor_raw::<D>(
-                *root.as_raw_ffi_any(),
-                storage.borrow_mut(),
-            ))
-        })
+        Self::run_visitor::<D>(*root.as_raw_ffi_any(), storage.borrow_mut())
     }
 }
 
@@ -522,7 +458,6 @@ impl 
super::dispatch::CallbackResult<Result<Option<VisitInterrupt>>>
 // 
-----------------------------------------------------------------------------
 // Outlined errors
 // 
-----------------------------------------------------------------------------
-// Keep construction and formatting scratch outside successful traversal 
frames.
 
 #[cold]
 #[inline(never)]
@@ -547,18 +482,8 @@ fn invalid_visit_hook_result_error() -> Error {
 // Perf note: Keep error formatting and context-allocation scratch out of 
visit frames.
 #[cold]
 #[inline(never)]
-fn annotate_visit_error(
-    error: Error,
-    type_index: i32,
-    small_str_len: u32,
-    data_union: TVMFFIAnyDataUnion,
-) -> Error {
-    let value = TVMFFIAny {
-        type_index,
-        small_str_len,
-        data_union,
-    };
-    let error = with_visit_error_context(error, value);
+fn annotate_visit_error(error: Error, value: TVMFFIAny) -> Error {
+    let error = update_visit_error_context(error, value);
     with_structural_error_context(
         error,
         "visit",
@@ -569,22 +494,16 @@ fn annotate_visit_error(
     )
 }
 
-// Perf note: Outline panic construction; the successful identity check stays 
small.
-#[cold]
-#[inline(never)]
-fn wrong_visitor_dispatcher() -> ! {
-    panic!("structural visitor called with a different dispatcher instance")
-}
-
 // 
-----------------------------------------------------------------------------
 // Private utility functions
 // 
-----------------------------------------------------------------------------
 
 #[inline(always)]
-fn dispatcher_context<D>(dispatch: &mut D) -> *mut c_void {
+fn dispatcher_ptr<D>(dispatch: &mut D) -> *mut c_void {
     std::ptr::from_mut(dispatch).cast()
 }
 
+// The visit result carrier, as C++: None continues; a VisitInterrupt or an 
Error stops.
 #[inline(always)]
 fn visit_result_raw(result: Result<Option<VisitInterrupt>>, raw: TVMFFIAny) -> 
TVMFFIAny {
     match result {
@@ -619,38 +538,6 @@ unsafe fn take_error(value: Any) -> Error {
     Error::move_from_any_after_check(&mut raw)
 }
 
-#[inline(always)]
-pub(crate) fn field_def_region(field: &TVMFFIFieldInfo, inherited: 
DefRegionKind) -> DefRegionKind {
-    // Precedence: a pattern region propagates; entering any kind inside it 
has no effect.
-    if inherited == DefRegionKind::Pattern {
-        DefRegionKind::Pattern
-    } else if field.flags & FLAG_SEQ_HASH_DEF_SIMPLE != 0 {
-        DefRegionKind::Simple
-    } else if field.flags & FLAG_SEQ_HASH_DEF_PATTERN != 0 {
-        DefRegionKind::Pattern
-    } else {
-        inherited
-    }
-}
-
-/// A simple definition applies to a FreeVar value itself, but not to
-/// the FreeVar's own reflected children: nested free vars there must resolve
-/// against an outer binding instead of rebinding. Mirrors C++
-/// `VisitReflectedFieldsExpected`.
-#[inline(always)]
-pub(crate) fn free_var_child_region(
-    inherited: DefRegionKind,
-    structural_eq_hash_kind: i32,
-) -> DefRegionKind {
-    if inherited == DefRegionKind::Simple
-        && structural_eq_hash_kind == 
TVMFFISEqHashKind::kTVMFFISEqHashKindFreeVar as i32
-    {
-        DefRegionKind::None
-    } else {
-        inherited
-    }
-}
-
 #[inline(always)]
 fn with_field_error_context(result: Any, name: &str) -> Any {
     if result.type_index() == TVMFFITypeIndex::kTVMFFIError as i32 {
@@ -674,60 +561,12 @@ fn structural_visit_column() -> TypeAttrColumn {
     *STRUCTURAL_VISIT_COLUMN
 }
 
-/// Visit every reflected field described by `info` and its ancestors in the
-/// same parent-to-child order as C++ `ForEachFieldInfoWithEarlyStop`.
-///
-/// # Safety
-///
-/// `info` must point to an immortal registered type-info record.
-pub(crate) unsafe fn for_each_field_info<B>(
-    info: *const crate::tvm_ffi_sys::TVMFFITypeInfo,
-    callback: &mut impl FnMut(&'static TVMFFIFieldInfo) -> ControlFlow<B>,
-) -> Option<B> {
-    // Ancestor slot 0 is the root Object. C++ starts at slot 1, walks toward
-    // the immediate parent, then visits the concrete type's own fields.
-    for depth in 1..(*info).type_depth {
-        let ancestor = *(*info).type_acenstors.offset(depth as isize);
-        if let Some(value) = visit_field_level(ancestor, callback) {
-            return Some(value);
-        }
-    }
-    visit_field_level(info, callback)
-}
-
-unsafe fn visit_field_level<B>(
-    info: *const crate::tvm_ffi_sys::TVMFFITypeInfo,
-    callback: &mut impl FnMut(&'static TVMFFIFieldInfo) -> ControlFlow<B>,
-) -> Option<B> {
-    if info.is_null() || (*info).fields.is_null() {
-        return None;
-    }
-    let fields = std::slice::from_raw_parts((*info).fields, (*info).num_fields 
as usize);
-    for field in fields {
-        // C reflection tables are immortal once registered.
-        let field: &'static TVMFFIFieldInfo = &*(field as *const 
TVMFFIFieldInfo);
-        if let ControlFlow::Break(value) = callback(field) {
-            return Some(value);
-        }
-    }
-    None
-}
-
 // 
-----------------------------------------------------------------------------
 // Prefix-only default traversal and native ABI operations
 // 
-----------------------------------------------------------------------------
 
-// Perf note: Raw carriers avoid materializing an owning Any on the success 
path.
-// Private C-unwind boundaries return this 16-byte carrier in x0/x1 on AArch64,
-// avoiding the hidden result slot observed with the Rust ABI while allowing
-// Rust cleanup to unwind. Native vtables remain extern "C".
-// Raw bits provide no ownership guard: each `_raw` result carries one owned 
ABI
-// value. Forward it exactly once or import it into Any before any operation
-// that can unwind or discard it, including destruction of an observer.
 impl StructuralVisitorObj {
-    /// Consume owning `result` from descent, adding borrowed `value` context 
on Error.
-    /// Internal callers supply valid tokens and keep the input live during 
annotation;
-    /// nonerrors transfer unchanged, and Error ownership is guarded through 
formatting.
+    /// Consume `result`, naming the borrowed `value` in it when it is an 
Error.
     #[inline(always)]
     fn with_visit_context_raw(result: TVMFFIAny, value: TVMFFIAny) -> 
TVMFFIAny {
         if result.type_index != TVMFFITypeIndex::kTVMFFIError as i32
@@ -739,29 +578,17 @@ impl StructuralVisitorObj {
             // SAFETY: the Error tag establishes the owned object's 
representation.
             unsafe {
                 let error = take_error(Any::from_raw_ffi_any(result));
-                Any::into_raw_ffi_any(
-                    annotate_visit_error(
-                        error,
-                        value.type_index,
-                        value.small_str_len,
-                        value.data_union,
-                    )
-                    .into(),
-                )
+                Any::into_raw_ffi_any(annotate_visit_error(error, 
value).into())
             }
         }
     }
 
-    /// Descend through the native hook or reflected fields using this runtime.
-    ///
-    /// The dispatcher field must already hold the caller's actual reborrow.
-    /// Descent itself never accesses D: every child reenters the same visitor
-    /// callback, which restores its incoming pointer before the next sibling.
-    /// Returns one owning raw None/interrupt/Error token.
+    /// Visit the children of `value` through its hook or reflected fields, 
without
+    /// dispatching `value` itself.
     ///
     /// # Safety
-    /// `runtime` must be this live engine and `value` a valid borrowed input 
whose
-    /// owner survives descent. Hooks may not retain the runtime or input 
borrow.
+    ///
+    /// `runtime` is live with its dispatcher published, and `value` outlives 
descent.
     #[inline(always)]
     unsafe fn visit_children_raw(runtime: StructuralVisitorHandle, value: 
TVMFFIAny) -> TVMFFIAny {
         if let Some(attr) = 
structural_visit_column().get_raw_ffi_any(value.type_index) {
@@ -773,53 +600,29 @@ impl StructuralVisitorObj {
         if value.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 
{
             TVMFFIAny::new()
         } else {
-            Self::visit_reflected_fields_raw(
-                runtime,
-                value.type_index,
-                value.small_str_len,
-                value.data_union,
-            )
+            Self::visit_reflected_fields_raw(runtime, value)
         }
     }
 
-    /// Reconstruct borrowed input from its scalar fields and visit registered 
fields
-    /// through live `runtime`. Return one owning None/interrupt/Error after 
local cleanup.
-    /// The private C-unwind ABI preserves Rust unwinding and AArch64 register 
returns;
-    /// public/native callback ABIs are unchanged.
+    /// Visit each reflected field of the object in `value`.
     ///
     /// # Safety
-    /// The input fields and runtime must be valid for synchronous descent; 
registered
-    /// reflection metadata must satisfy its getter/offset contracts.
-    // Perf note: Keep reflection scratch outside recursive frames. This 
fallback
-    // can be frequent, so inline(never) is intentional without cold.
-    // The AArch64 C ABI returns TVMFFIAny in registers; C-unwind preserves
-    // Rust cleanup if reflected traversal panics inside this private helper.
+    ///
+    /// As [`Self::visit_children_raw`]. Outlined (frequent, not cold) to keep 
reflection
+    /// scratch out of recursive frames.
     #[inline(never)]
     unsafe extern "C-unwind" fn visit_reflected_fields_raw(
         runtime: StructuralVisitorHandle,
-        type_index: i32,
-        small_str_len: u32,
-        data_union: TVMFFIAnyDataUnion,
+        value: TVMFFIAny,
     ) -> TVMFFIAny {
-        let value = TVMFFIAny {
-            type_index,
-            small_str_len,
-            data_union,
-        };
         let type_info = unsafe { TVMFFIGetTypeInfo(value.type_index) };
         if type_info.is_null() {
             return 
Any::into_raw_ffi_any(unregistered_visit_type_error(value.type_index).into());
         }
-        let seq_hash_kind = unsafe {
-            let metadata = (*type_info).metadata;
-            if metadata.is_null() {
-                TVMFFISEqHashKind::kTVMFFISEqHashKindUnsupported as i32
-            } else {
-                (*metadata).structural_eq_hash_kind
-            }
-        };
-        let kind = std::mem::transmute::<i32, 
DefRegionKind>(*(*runtime).def_region_mode.get());
-        let def_region_kind = free_var_child_region(kind, seq_hash_kind);
+        let def_region_kind = free_var_child_region(
+            std::mem::transmute::<i32, 
DefRegionKind>(*(*runtime).def_region_mode.get()),
+            seq_hash_kind(type_info),
+        );
         let object = unsafe { value.data_union.v_obj } as *mut u8;
         let halted = unsafe {
             for_each_field_info(type_info, &mut |field| {
@@ -834,12 +637,11 @@ impl StructuralVisitorObj {
         Any::into_raw_ffi_any(halted.unwrap_or_else(Any::new))
     }
 
-    /// Visit one registered `field` in borrowed `object` using 
`inherited_region`.
-    /// Own getter output through recursive traversal and return an owning 
result.
+    /// Visit one reflected `field` of `object` under `inherited_region`.
     ///
     /// # Safety
-    /// `runtime` and `object` must be live; `field` must describe valid 
storage and a
-    /// registered getter for that object. Neither raw input transfers 
ownership.
+    ///
+    /// `runtime` and `object` are live, and `field` describes `object`'s 
storage.
     unsafe fn visit_reflected_field(
         runtime: StructuralVisitorHandle,
         object: *mut u8,
@@ -870,33 +672,29 @@ impl StructuralVisitorObj {
         )
     }
 
-    /// Invoke the live visitor vtable on borrowed `value`, returning one 
owning token.
-    /// Internal callers keep runtime/input valid and publish the dispatcher 
reborrow.
-    /// None bypasses dispatch; native callbacks report failures without 
unwinding.
+    /// Dispatch borrowed `value` through the runtime's vtable.
     #[inline(always)]
-    fn call_visitor_raw(visitor: StructuralVisitorHandle, value: TVMFFIAny) -> 
TVMFFIAny {
+    fn call_visitor_raw(runtime: StructuralVisitorHandle, value: TVMFFIAny) -> 
TVMFFIAny {
         if value.type_index == TVMFFITypeIndex::kTVMFFINone as i32 {
             core::hint::cold_path();
             return TVMFFIAny::new();
         }
         unsafe {
-            let callback = (*(*visitor).vtable).visit;
-            callback(visitor, AnyView::from_raw_ffi_any(value))
+            let callback = (*(*runtime).vtable).visit;
+            callback(runtime, AnyView::from_raw_ffi_any(value))
         }
     }
 
-    /// Invoke a native or packed hook with borrowed `visitor`, `value` and 
`hook`.
-    /// Return one owning None/Error/VisitInterrupt; packed results are 
checked.
+    /// Call the registered visit `hook` (native pointer or packed function) 
on `value`.
     ///
     /// # Safety
-    /// The runtime and both borrowed inputs must be valid and live for this 
call;
-    /// the inputs transfer no ownership. Publish the current exclusive 
dispatcher
-    /// reborrow first. A native hook must be a non-null function with the 
visit ABI
-    /// accepting this runtime's complete layout. All hooks must obey
-    /// [`StructuralVisitorBase`]'s synchronous, same-thread, non-escaping 
contract.
+    ///
+    /// `runtime` is live with its dispatcher published, `value` and `hook` 
outlive the
+    /// call, and a native hook has the visit ABI for this runtime's layout 
and obeys
+    /// [`StructuralVisitorBase`]'s non-escaping contract.
     #[inline(always)]
     pub unsafe fn call_structural_visit_hook_raw(
-        visitor: *mut Self,
+        runtime: *mut Self,
         value: TVMFFIAny,
         hook: TVMFFIAny,
     ) -> TVMFFIAny {
@@ -906,59 +704,29 @@ impl StructuralVisitorObj {
                 // Native pointer registration is an unsafe contract: a 
non-null
                 // callback with this ABI, borrowed runtime lifetime and 
owning result.
                 let hook: FStructuralVisit = std::mem::transmute(pointer);
-                hook(visitor, AnyView::from_raw_ffi_any(value))
+                hook(runtime, AnyView::from_raw_ffi_any(value))
             } else {
                 core::hint::cold_path();
-                Self::call_structural_visit_hook_slow_raw(
-                    visitor,
-                    value.type_index,
-                    value.small_str_len,
-                    value.data_union,
-                    hook.type_index,
-                    hook.small_str_len,
-                    hook.data_union,
-                )
+                Self::call_structural_visit_hook_slow_raw(runtime, value, hook)
             }
         }
     }
 
-    /// Reconstruct borrowed value/hook from their scalar fields for a packed 
call.
-    /// Internal callers keep `visitor` and both inputs live; no input 
transfers ownership.
-    /// Validate the owning packed result and release temporary owners before 
exporting
-    /// one raw token. Private C-unwind preserves Rust cleanup and AArch64 
register
-    /// returns without changing the public or native callback ABI.
-    // Keep packed calls and malformed registrations out of the native-hook 
hot path.
-    // Outline uncommon packed-call scratch to keep native visit frames small.
-    // Match the native raw-result ABI (registers on AArch64), without adding
-    // an abort boundary around Rust packed-call cleanup.
+    /// The packed-function arm of [`Self::call_structural_visit_hook_raw`], 
outlined as cold;
+    /// its result tag is checked.
     #[cold]
     #[inline(never)]
     extern "C-unwind" fn call_structural_visit_hook_slow_raw(
-        visitor: StructuralVisitorHandle,
-        value_type_index: i32,
-        value_small_str_len: u32,
-        value_data: TVMFFIAnyDataUnion,
-        hook_type_index: i32,
-        hook_small_str_len: u32,
-        hook_data: TVMFFIAnyDataUnion,
+        runtime: StructuralVisitorHandle,
+        value: TVMFFIAny,
+        hook: TVMFFIAny,
     ) -> TVMFFIAny {
-        // Construct addressable packed-call arguments only on this cold path.
-        let value = TVMFFIAny {
-            type_index: value_type_index,
-            small_str_len: value_small_str_len,
-            data_union: value_data,
-        };
-        let hook = TVMFFIAny {
-            type_index: hook_type_index,
-            small_str_len: hook_small_str_len,
-            data_union: hook_data,
-        };
         // Packed hooks (including Python class methods) can return any 
well-formed
         // Any through safe APIs. Their result tag needs validation before 
decoding.
         let result = unsafe {
             
Function::try_from(AnyView::from_raw_ffi_any(hook)).and_then(|function| {
                 // Borrow the live runtime for this synchronous hook; it may 
not retain it.
-                let object = visitor.cast::<TVMFFIObject>();
+                let object = runtime.cast::<TVMFFIObject>();
                 let mut runtime = TVMFFIAny::new();
                 runtime.type_index = (*object).type_index;
                 runtime.data_union.v_obj = object;
@@ -1009,14 +777,14 @@ impl StructuralVisitorObj {
 
 // Generic runtime: only this implementation projects the dispatcher after 
Base.
 impl<Base: StructuralVisitorBase> StructuralVisitEngine<Base> {
-    /// Recover the Rust engine whose first field is this ABI base.
+    /// The engine whose first field is the native prefix `runtime`.
     ///
     /// # Safety
-    /// The handle must belong to the live, synchronous Rust traversal that 
created
+    /// `runtime` must belong to the live, synchronous Rust traversal that 
created
     /// this exact repr(C) engine. An arbitrary native visitor is not such an 
engine.
     #[inline(always)]
-    unsafe fn from_handle(handle: StructuralVisitorHandle) -> *mut Self {
-        handle.cast()
+    unsafe fn from_handle(runtime: StructuralVisitorHandle) -> *mut Self {
+        runtime.cast()
     }
 
     /// Publish the current exclusive `dispatch` reborrow and visit borrowed 
`raw`.
@@ -1048,10 +816,10 @@ impl<Base: StructuralVisitorBase> 
StructuralVisitEngine<Base> {
         runtime: StructuralVisitorHandle,
         dispatch: &mut D,
     ) -> *mut c_void {
-        let current = dispatcher_context(dispatch);
+        let current = dispatcher_ptr(dispatch);
         if current != (*Self::from_handle(runtime)).dispatcher {
             core::hint::cold_path();
-            wrong_visitor_dispatcher();
+            wrong_dispatcher();
         }
         current
     }
@@ -1103,7 +871,7 @@ impl<Base: StructuralVisitorBase> 
StructuralVisitEngine<Base> {
                 (AnyView::from_raw_ffi_any(raw), &mut visitor),
             ) {
                 Some(result) => visit_result_raw(result, raw),
-                None => Self::default_visit_raw(runtime, 
dispatcher_context(dispatch), raw),
+                None => Self::default_visit_raw(runtime, 
dispatcher_ptr(dispatch), raw),
             }
         };
         // The enclosing callback may resume using its ancestor mutable borrow.
@@ -1123,7 +891,7 @@ impl<Base: StructuralVisitorBase> 
StructuralVisitEngine<Base> {
     ) -> StructuralVisitorView<'a, D, Base> {
         StructuralVisitorView {
             runtime,
-            _scope: PhantomData,
+            _marker: PhantomData,
         }
     }
 
@@ -1148,21 +916,18 @@ impl<Base: StructuralVisitorBase> 
StructuralVisitEngine<Base> {
         )
     }
 
-    /// Run the public visit/walk adapter with borrowed `root` and exclusive 
`dispatch`.
-    /// Internal callers keep the root owner live. Own the result across 
engine Drop,
-    /// including unwind, then transfer one raw None/interrupt/Error token. 
Hooks must
-    /// release temporary runtime owners and cannot retain the scoped 
dispatcher.
-    pub(super) fn run_visitor_raw<D>(root: TVMFFIAny, dispatch: &mut D) -> 
TVMFFIAny
+    /// Visit borrowed `root` with `dispatch` on a fresh engine; the root's 
owner outlives it.
+    pub(super) fn run_visitor<D>(
+        root: TVMFFIAny,
+        dispatch: &mut D,
+    ) -> Result<Option<VisitInterrupt>>
     where
         for<'s, 'v, 'c, 'r> &'s mut D: crate::Dispatcher<
             (AnyView<'v>, &'c mut StructuralVisitorView<'r, D, Base>),
             Option<Result<Option<VisitInterrupt>>>,
         >,
     {
-        let base = match Base::new() {
-            Ok(base) => base,
-            Err(error) => return Any::into_raw_ffi_any(error.into()),
-        };
+        let base = Base::new()?;
         let type_index = Base::type_index();
         // The managed runtime may borrow its dispatcher only for this call.
         // Trusted hooks release all temporary handles before the owner is 
dropped.
@@ -1170,24 +935,24 @@ impl<Base: StructuralVisitorBase> 
StructuralVisitEngine<Base> {
             ObjectArc::<Object>::new_opaque_unchecked(
                 StructuralVisitEngine {
                     base,
-                    dispatcher: dispatcher_context(dispatch),
+                    dispatcher: dispatcher_ptr(dispatch),
                 },
                 type_index,
             )
         };
-        let handle = ObjectArc::as_mut_ptr(&mut 
engine).cast::<StructuralVisitorObj>();
+        let runtime = ObjectArc::as_mut_ptr(&mut 
engine).cast::<StructuralVisitorObj>();
         // The engine and outer dispatcher storage stay stationary for the 
whole run.
         // Only raw field projections cross recursion; no whole-engine borrow 
survives.
         unsafe {
-            (*handle).vtable = Self::vtable::<D>();
-            *(*handle).def_region_mode.get() = DefRegionKind::None as i32;
+            (*runtime).vtable = Self::vtable::<D>();
+            *(*runtime).def_region_mode.get() = DefRegionKind::None as i32;
         }
         // Keep the result owned while releasing the runtime, including on 
unwind.
         let result =
-            unsafe { 
Any::from_raw_ffi_any(StructuralVisitorObj::call_visitor_raw(handle, root)) };
+            unsafe { 
Any::from_raw_ffi_any(StructuralVisitorObj::call_visitor_raw(runtime, root)) };
         // Trusted hooks have released every temporary strong/weak runtime 
reference.
         drop(engine);
-        Any::into_raw_ffi_any(result)
+        visit_result_from_any(result)
     }
 }
 
diff --git a/rust/tvm-ffi/src/extra/structural_walk.rs 
b/rust/tvm-ffi/src/extra/structural_walk.rs
index e92b0eeb..99e0b580 100644
--- a/rust/tvm-ffi/src/extra/structural_walk.rs
+++ b/rust/tvm-ffi/src/extra/structural_walk.rs
@@ -23,8 +23,7 @@
 //! the non-unwinding native callback boundary aborts the process.
 
 use super::structural_visit::{
-    visit_result_from_any, DefRegionKind, StructuralVisitEngine, 
StructuralVisitorView,
-    VisitInterrupt,
+    DefRegionKind, StructuralVisitEngine, StructuralVisitorView, 
VisitInterrupt,
 };
 use crate::{Any, AnyView, Dispatcher, IntoDispatcher, Result};
 use std::borrow::BorrowMut;
@@ -171,26 +170,14 @@ where
     for<'s, 'v> &'s mut D: Dispatcher<(AnyView<'v>, DefRegionKind), 
Option<Result<WalkResult>>>,
 {
     let root = *root.as_raw_ffi_any();
-    // Take ownership of the raw result right after the native call.
-    let result = match order {
+    match order {
         WalkOrder::PreOrder => {
-            let mut visitor = WalkVisitor::<D, true> { observer };
-            let raw = StructuralVisitEngine::run_visitor_raw::<WalkVisitor<'_, 
D, true>>(
-                root,
-                &mut visitor,
-            );
-            unsafe { Any::from_raw_ffi_any(raw) }
+            StructuralVisitEngine::run_visitor(root, &mut WalkVisitor::<D, 
true> { observer })
         }
         WalkOrder::PostOrder => {
-            let mut visitor = WalkVisitor::<D, false> { observer };
-            let raw = StructuralVisitEngine::run_visitor_raw::<WalkVisitor<'_, 
D, false>>(
-                root,
-                &mut visitor,
-            );
-            unsafe { Any::from_raw_ffi_any(raw) }
+            StructuralVisitEngine::run_visitor(root, &mut WalkVisitor::<D, 
false> { observer })
         }
-    };
-    visit_result_from_any(result)
+    }
 }
 
 /// Walk `root` with an observer, the Rust analog of C++
diff --git a/rust/tvm-ffi/src/extra/unchanged.rs 
b/rust/tvm-ffi/src/extra/unchanged.rs
index 66678193..4a0c8182 100644
--- a/rust/tvm-ffi/src/extra/unchanged.rs
+++ b/rust/tvm-ffi/src/extra/unchanged.rs
@@ -302,11 +302,7 @@ impl UnchangedOr<Any> {
             // Transfer ownership directly into the checked cold conversion.
             return unsafe {
                 let raw = Any::into_raw_ffi_any(data);
-                Err(structural_error_from_raw(
-                    raw.type_index,
-                    raw.small_str_len,
-                    raw.data_union,
-                ))
+                Err(structural_error_from_raw(raw))
             };
         }
         Ok(Self {
diff --git a/rust/tvm-ffi/src/extra/visit_error_context.rs 
b/rust/tvm-ffi/src/extra/visit_error_context.rs
new file mode 100644
index 00000000..c249a544
--- /dev/null
+++ b/rust/tvm-ffi/src/extra/visit_error_context.rs
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+//! Rust side of C++ `tvm/ffi/extra/visit_error_context.h`: the context an 
error
+//! carries to name the nodes a failed visit unwound through.
+
+use crate::any::AnyView;
+use crate::collections::array::Array;
+use crate::derive::Object;
+use crate::error::Error;
+use crate::object::{self, Object, ObjectArc, ObjectRef, ObjectRefCore};
+use crate::tvm_ffi_sys::{TVMFFIAny, TVMFFIObject, TVMFFITypeIndex};
+
+/// Rust binding of C++ `VisitErrorContextObj`, the payload that
+/// `Error::extra_context` carries to name the nodes a failed visit unwound 
through.
+#[repr(C)]
+#[derive(Object)]
+#[type_key = "ffi.VisitErrorContext"]
+#[type_final]
+pub(crate) struct VisitErrorContextObj {
+    base: Object,
+    /// Visited nodes, innermost first; C++ `ObjectRef` is nullable.
+    reverse_visit_pattern: Array<Option<ObjectRef>>,
+    /// The `extra_context` the error carried before this context replaced it.
+    prev_error_context: Option<ObjectRef>,
+}
+
+/// Name the visited object in `raw` in the error's visit context, as C++
+/// `detail::UpdateVisitErrorContext`.
+#[cold]
+pub(crate) fn update_visit_error_context(mut error: Error, raw: TVMFFIAny) -> 
Error {
+    // Copy-on-write at each level: the Error, its context and the context's 
pattern
+    // are each copied only when shared, so an error owned by the unwinding 
frame is
+    // appended in place.
+    if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
+        return error;
+    }
+    // SAFETY: the traversal input remains live during annotation. Conversion
+    // acquires ownership before the temporary view ends; raw is an object tag.
+    let Ok(node) = ObjectRef::try_from(unsafe { AnyView::from_raw_ffi_any(raw) 
}) else {
+        return error;
+    };
+    let as_context = |context: &ObjectRef| {
+        let object = ObjectArc::as_ptr(ObjectRef::data(context));
+        // SAFETY: `context` keeps its object alive; the type is checked first.
+        unsafe {
+            object::is_instance_of::<VisitErrorContextObj>(
+                (*object.cast::<TVMFFIObject>()).type_index,
+            )
+            .then(|| &*object.cast::<VisitErrorContextObj>())
+        }
+    };
+    // Callback, policy and default descent can report the same frame.
+    if let Some(context) = error.extra_context().and_then(as_context) {
+        if context
+            .reverse_visit_pattern
+            .iter()
+            .next_back()
+            .and_then(Option::as_ref)
+            .is_some_and(|last| last.same_as(&node))
+        {
+            return error;
+        }
+    }
+    let slot = error.extra_context_mut();
+    let previous = slot.take();
+    let context = match previous {
+        Some(previous) if as_context(&previous).is_some() => {
+            // SAFETY: `previous` was checked to be a `VisitErrorContextObj`.
+            let mut context = unsafe {
+                ObjectArc::from_raw(
+                    ObjectArc::into_raw(ObjectRef::into_data(previous))
+                        .cast::<VisitErrorContextObj>(),
+                )
+            };
+            if !ObjectArc::is_unique(&context) {
+                context = ObjectArc::new(VisitErrorContextObj {
+                    base: Object::new(),
+                    reverse_visit_pattern: 
context.reverse_visit_pattern.clone(),
+                    prev_error_context: context.prev_error_context.clone(),
+                });
+            }
+            // SAFETY: this handle is the context's only reference.
+            unsafe {
+                (*ObjectArc::as_mut_ptr(&mut context))
+                    .reverse_visit_pattern
+                    .push(Some(node))
+            };
+            context
+        }
+        previous => ObjectArc::new(VisitErrorContextObj {
+            base: Object::new(),
+            reverse_visit_pattern: Array::from_vec(vec![Some(node)]),
+            prev_error_context: previous,
+        }),
+    };
+    // SAFETY: every object starts with the root `Object` header.
+    *slot = Some(unsafe {
+        ObjectRef::from_data(ObjectArc::from_raw(
+            ObjectArc::into_raw(context).cast::<Object>(),
+        ))
+    });
+    error
+}
diff --git a/rust/tvm-ffi/src/lib.rs b/rust/tvm-ffi/src/lib.rs
index 76b19503..7431787c 100644
--- a/rust/tvm-ffi/src/lib.rs
+++ b/rust/tvm-ffi/src/lib.rs
@@ -116,7 +116,7 @@ pub use crate::type_traits::AnyCompatible;
 /// strictly; `&Type` (such as `&Array<i64>` or `&tvm_ffi::String`) or
 /// `&NodeObj`, which borrow the value or the object node in place without
 /// changing a reference count; `MutationView<'_, T>`,
-/// which keeps the permission to mutate in place; or `AnyView<'_>`, which
+/// which keeps the in-place mode; or `AnyView<'_>`, which
 /// matches every value and must be the last handler.
 ///
 /// Only the outer `None` means that no handler matched: a handler error, or a
@@ -169,7 +169,7 @@ pub use tvm_ffi_macros::dispatch;
 ///   `Array<Any>`.
 /// * `Type(ref name)` borrows a managed reference, and `NodeObj(ref name)`
 ///   borrows the object node, without changing its reference count.
-/// * `MutationView<Type>(name)` moves the permission to mutate in place into a
+/// * `MutationView<Type>(name)` moves the in-place mode into a
 ///   typed view.
 ///
 /// Matching is strict: an `i64` arm does not match a stored `f64`, and a value
diff --git a/rust/tvm-ffi/src/match_any_internal.rs 
b/rust/tvm-ffi/src/match_any_internal.rs
index c999b807..b57009a6 100644
--- a/rust/tvm-ffi/src/match_any_internal.rs
+++ b/rust/tvm-ffi/src/match_any_internal.rs
@@ -50,10 +50,10 @@ pub struct OwnedSource(crate::Any);
 #[doc(hidden)]
 pub struct ViewSource<'a>(AnyView<'a>);
 #[doc(hidden)]
-pub struct CapabilitySource<'a>(Option<crate::MutationView<'a>>);
+pub struct MutationSource<'a>(Option<crate::MutationView<'a>>);
 
 /// Object references move into an owning Any; inherent adapters preserve view 
and
-/// capability lifetimes independently of the local holder's lifetime.
+/// view lifetimes independently of the local holder's lifetime.
 #[doc(hidden)]
 pub trait PrepareSource {
     type Source;
@@ -89,8 +89,8 @@ impl<'a, T: ?Sized> SourceProbe<&'a T> {
 }
 impl<'a, T> SourceProbe<crate::MutationView<'a, T>> {
     #[inline(always)]
-    pub fn prepare(&mut self) -> CapabilitySource<'a> {
-        CapabilitySource(Some(self.0.take().unwrap().into_untyped()))
+    pub fn prepare(&mut self) -> MutationSource<'a> {
+        MutationSource(Some(self.0.take().unwrap().into_untyped()))
     }
 }
 
@@ -120,7 +120,7 @@ impl SourceView for ViewSource<'_> {
         self.0.as_raw_ffi_any()
     }
 }
-impl SourceView for CapabilitySource<'_> {
+impl SourceView for MutationSource<'_> {
     #[inline(always)]
     fn view(&self) -> AnyView<'_> {
         self.0.as_ref().unwrap().as_any_view()
@@ -131,7 +131,7 @@ impl SourceView for CapabilitySource<'_> {
     }
 }
 
-/// A rejected guard drops an ordinary result or returns the original 
capability.
+/// A rejected guard drops an ordinary result or returns the original view.
 /// There is no Drop implementation, so native match guards retain Rust's usual
 /// restriction against moving their bindings before the guard succeeds.
 #[doc(hidden)]
@@ -153,7 +153,7 @@ impl<S> Restore<()> for S {
     #[inline(always)]
     fn restore(&mut self, _: ()) {}
 }
-impl<'a> Restore<crate::MutationView<'a>> for CapabilitySource<'a> {
+impl<'a> Restore<crate::MutationView<'a>> for MutationSource<'a> {
     #[inline(always)]
     fn restore(&mut self, recovery: crate::MutationView<'a>) {
         debug_assert!(self.0.is_none());
@@ -162,7 +162,7 @@ impl<'a> Restore<crate::MutationView<'a>> for 
CapabilitySource<'a> {
 }
 
 /// Type-directed matching. The source parameter also expresses whether an
-/// aliased result can retain the input lifetime or transfer its capability.
+/// aliased result can retain the input lifetime or transfer its view.
 #[doc(hidden)]
 pub trait MatchPattern<S>: Sized {
     type Recovery;
@@ -210,24 +210,22 @@ impl<'b> MatchPattern<&'b mut OwnedSource> for 
AnyView<'b> {
         })
     }
 }
-impl<'a, 'b> MatchPattern<&'b mut CapabilitySource<'a>> for AnyView<'b> {
+impl<'a, 'b> MatchPattern<&'b mut MutationSource<'a>> for AnyView<'b> {
     type Recovery = ();
     #[inline(always)]
-    fn try_match(source: &'b mut CapabilitySource<'a>) -> Result<Matched<Self, 
()>, ()> {
+    fn try_match(source: &'b mut MutationSource<'a>) -> Result<Matched<Self, 
()>, ()> {
         Ok(Matched {
             value: source.view(),
             recover: drop,
         })
     }
 }
-impl<'a, 'b, T: crate::type_traits::ContainerElement> MatchPattern<&'b mut 
CapabilitySource<'a>>
+impl<'a, 'b, T: crate::type_traits::ContainerElement> MatchPattern<&'b mut 
MutationSource<'a>>
     for crate::MutationView<'a, T>
 {
     type Recovery = crate::MutationView<'a>;
     #[inline(always)]
-    fn try_match(
-        source: &'b mut CapabilitySource<'a>,
-    ) -> Result<Matched<Self, Self::Recovery>, ()> {
+    fn try_match(source: &'b mut MutationSource<'a>) -> Result<Matched<Self, 
Self::Recovery>, ()> {
         match source.0.take().unwrap().downcast::<T>() {
             Ok(value) => {
                 if unsafe { 
T::container_match_constraints(value.as_any_view().as_raw_ffi_any()) } {
@@ -292,7 +290,7 @@ impl<'b, T: crate::type_traits::DowncastRefFromAny + 
'static, S: SourceView>
         // such as `&Add` points into the cell, an object type into the heap.
         let node = unsafe { T::downcast_ref_from_any(source.cell()) 
}.ok_or(())? as *const T;
         // SAFETY: the checked value is borrowed from source for 'b. No owning
-        // conversion or capability transfer can occur while this borrow lives.
+        // conversion or view transfer can occur while this borrow lives.
         Ok(Matched {
             value: unsafe { &*node },
             recover: drop,
diff --git a/rust/tvm-ffi/src/object.rs b/rust/tvm-ffi/src/object.rs
index 316b3243..ccfc8cc6 100644
--- a/rust/tvm-ffi/src/object.rs
+++ b/rust/tvm-ffi/src/object.rs
@@ -48,19 +48,8 @@ pub struct ObjectArc<T: ObjectCore> {
     _phantom: std::marker::PhantomData<T>,
 }
 
-// Not `Send`/`Sync` by default: an object's thread safety is that of its 
(often
-// C++) implementation, which the handle cannot see. An object type opts in 
with
-// `ImmutableObject`; tvm-ffi's own immutable handles opt in explicitly.
-
-/// An object type whose shared instances are never mutated, so handles to it 
may
-/// cross threads.
-///
-/// A handle `ObjectArc<T>`, and every reference built on it, is `Send + Sync`
-/// when `T: ImmutableObject` and `T`'s fields are themselves `Send + Sync`, so
-/// a field such as `Any`, which may hold a mutable object, keeps the handle
-/// single-threaded. The stub generator implements it for each class whose C++
-/// declaration is not `_type_mutable`. An erased `ObjectRef` may point at any
-/// object, so it never crosses threads.
+/// An object type whose shared instances are never mutated, so `ObjectArc<T>` 
is
+/// `Send + Sync` when `T`'s fields are.
 ///
 /// # Safety
 ///
@@ -655,10 +644,6 @@ pub mod unsafe_ {
     }
 }
 
-//---------------------
-// Object
-//---------------------
-
 impl Object {
     #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
@@ -681,10 +666,6 @@ unsafe impl ObjectCore for Object {
     }
 }
 
-//---------------------
-// ObjectArc
-//---------------------
-
 // Allocate and initialize the normal FFI header while preserving the concrete
 // payload's alignment and drop/layout deleter. The payload starts with an 
Object.
 unsafe fn allocate_object<T>(data: T, type_index: i32) -> NonNull<T> {
diff --git a/rust/tvm-ffi/src/type_traits.rs b/rust/tvm-ffi/src/type_traits.rs
index cb849cfe..268a82aa 100644
--- a/rust/tvm-ffi/src/type_traits.rs
+++ b/rust/tvm-ffi/src/type_traits.rs
@@ -240,14 +240,17 @@ pub trait ContainerElement: container_element_ops::Ops {}
 impl<T: AnyCompatible> ContainerElement for T {}
 impl ContainerElement for Any {}
 
-/// Types whose value an FFI `Any` cell stores in place, so `&Self` can be
-/// borrowed from the cell, as [`crate::Array`] indexing does.
+/// A type whose value an FFI cell stores in place, so `&Self` borrows from the
+/// cell, as [`Array`](crate::Array) indexing does.
+///
+/// A reference type implemented by hand gets it from
+/// [`unsafe_impl_ref_downcast!`](crate::unsafe_impl_ref_downcast).
 ///
 /// # Safety
 ///
-/// For a cell that passes `container_check_any_strict` for `Self`,
-/// `ref_from_any_unchecked` must return a reference into that cell that is a 
valid
-/// `Self` for as long as the cell is borrowed.
+/// For a cell that `Self` strictly accepts, `ref_from_any_unchecked` must
+/// return a reference into that cell that is a valid `Self` for as long as the
+/// cell is borrowed.
 #[doc(hidden)]
 pub unsafe trait RefFromAnyUnchecked: ContainerElement {
     /// Borrow the value stored in `cell`.
@@ -351,10 +354,10 @@ unsafe impl<T: crate::object::ObjectRefCore> 
DowncastRefFromAny for Option<T> {
     }
 }
 
-/// Types that [`crate::Any::downcast_ref`] and 
[`crate::AnyView::downcast_ref`]
-/// can borrow from an FFI cell in place: object types (`ArrayObj`), and the
-/// [`RefFromAnyUnchecked`] types (managed references such as `Array<T>`, 
`String`,
-/// `i64`).
+/// A type that [`Any::downcast_ref`] and [`AnyView::downcast_ref`] borrow from
+/// an FFI cell in place: object types (`ArrayObj`), and the
+/// [`RefFromAnyUnchecked`] types (managed references such as `Array<T>`,
+/// `String`, `i64`).
 ///
 /// # Safety
 ///
@@ -385,7 +388,8 @@ unsafe impl<T: crate::object::ObjectCore> 
DowncastRefFromAny for T {
     }
 }
 
-/// Borrow `cell` as a [`RefFromAnyUnchecked`] type when it strictly holds one.
+/// Borrow `cell` as a [`RefFromAnyUnchecked`] type when it strictly holds one:
+/// the [`DowncastRefFromAny`] of such a type.
 ///
 /// # Safety
 ///
@@ -402,7 +406,7 @@ pub unsafe fn downcast_ref_from_any_in_place<T: 
RefFromAnyUnchecked>(
     }
 }
 
-/// Types that an object reference's [`ObjectRefCore::downcast_ref`] can borrow
+/// A type that an object reference's [`ObjectRefCore::downcast_ref`] borrows
 /// from the reference's object pointer: object types (`ArrayObj`), and managed
 /// references that are exactly one object pointer (`Array<T>`, every
 /// `#[derive(ObjectRef)]` type).
@@ -438,7 +442,8 @@ unsafe impl<T: crate::object::ObjectCore> 
DowncastRefFromObject for T {
 }
 
 /// Borrow the object pointer at `place` as the one-pointer reference type `T`
-/// when the object strictly is a `T`.
+/// when the object strictly is a `T`: the [`DowncastRefFromObject`] of such a
+/// type.
 ///
 /// # Safety
 ///
@@ -456,6 +461,10 @@ pub unsafe fn downcast_ref_from_object_in_place<T: 
RefFromAnyUnchecked>(
         )
     };
     let object = *place;
+    // An object header always carries an object-range type index.
+    core::hint::assert_unchecked(
+        (*object).type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32,
+    );
     let mut cell = TVMFFIAny::new();
     cell.type_index = (*object).type_index;
     cell.data_union.v_obj = object;
diff --git a/rust/tvm-ffi/tests/test_structural_mutate.rs 
b/rust/tvm-ffi/tests/test_structural_mutate.rs
index 914e0c24..5f0a2faf 100644
--- a/rust/tvm-ffi/tests/test_structural_mutate.rs
+++ b/rust/tvm-ffi/tests/test_structural_mutate.rs
@@ -69,6 +69,49 @@ struct RecursiveEntryMutator {
     owned_value_pointer: Option<usize>,
 }
 
+fn probe_remap(
+    dispatch: &mut ManualIncrement,
+    mutator: &mut StructuralMutatorView<'_, ManualIncrement>,
+    key: Any,
+) -> Result<UnchangedOr<Any>> {
+    assert!(mutator
+        .var_remap_get(dispatch, AnyView::from(&key))?
+        .is_none());
+    assert!(mutator
+        .var_remap_get(dispatch, AnyView::from(&1_i64))
+        .is_err());
+    assert!(mutator
+        .var_remap_set(dispatch, AnyView::from(&1_i64), &Any::new())
+        .is_err());
+    let initial = mutator.def_region_kind();
+    mutator.with_def_region_kind(DefRegionKind::Pattern, |mutator| {
+        assert_eq!(mutator.def_region_kind(), DefRegionKind::Pattern);
+        mutator.var_remap_set(dispatch, AnyView::from(&key), &Any::new())?;
+        assert_eq!(
+            mutator
+                .var_remap_get(dispatch, AnyView::from(&key))?
+                .unwrap()
+                .type_index(),
+            TypeIndex::kTVMFFINone as i32
+        );
+        // A None replacement does not suppress reflected descent.
+        let result = mutator.mutate(dispatch, 
MutationView::borrowed(AnyView::from(&key)))?;
+        assert_eq!(
+            RemapNode::try_from(result.into_option().unwrap_or_else(|| 
key.clone()))?
+                .data
+                .value,
+            8
+        );
+        mutator.var_remap_set(dispatch, AnyView::from(&key), &Any::from(41i64))
+    })?;
+    assert_eq!(mutator.def_region_kind(), initial);
+    let replacement = mutator
+        .var_remap_get(dispatch, AnyView::from(&key))?
+        .unwrap();
+    dispatch.remapped = Some(replacement.clone());
+    Ok(UnchangedOr::changed(replacement))
+}
+
 impl<'v, 'c, 'r>
     Dispatcher<
         (
@@ -88,39 +131,7 @@ impl<'v, 'c, 'r>
     ) -> Option<Result<UnchangedOr<Any>>> {
         Some(if strict_bool(value.as_any_view()) == Some(true) {
             let key = self.remap_probe.as_ref().unwrap().clone();
-            (|| {
-                assert!(mutator.var_remap_get(self, 
AnyView::from(&key))?.is_none());
-                assert!(mutator.var_remap_get(self, 
AnyView::from(&1_i64)).is_err());
-                assert!(mutator
-                    .var_remap_set(self, AnyView::from(&1_i64), &Any::new())
-                    .is_err());
-                let initial = mutator.def_region_kind();
-                mutator.with_def_region_kind(DefRegionKind::Pattern, |mutator| 
{
-                    assert_eq!(mutator.def_region_kind(), 
DefRegionKind::Pattern);
-                    mutator.var_remap_set(self, AnyView::from(&key), 
&Any::new())?;
-                    assert_eq!(
-                        mutator
-                            .var_remap_get(self, AnyView::from(&key))?
-                            .unwrap()
-                            .type_index(),
-                        TypeIndex::kTVMFFINone as i32
-                    );
-                    // A None replacement does not suppress reflected descent.
-                    let result =
-                        mutator.mutate(self, 
MutationView::borrowed(AnyView::from(&key)))?;
-                    assert_eq!(
-                        
RemapNode::try_from(result.into_option().unwrap_or_else(|| key.clone()))?
-                            .data
-                            .value,
-                        8
-                    );
-                    mutator.var_remap_set(self, AnyView::from(&key), 
&Any::from(41i64))
-                })?;
-                assert_eq!(mutator.def_region_kind(), initial);
-                let replacement = mutator.var_remap_get(self, 
AnyView::from(&key))?.unwrap();
-                self.remapped = Some(replacement.clone());
-                Ok(UnchangedOr::changed(replacement))
-            })()
+            probe_remap(self, mutator, key)
         } else if let Some(integer) = 
value.as_any_view().downcast_ref::<i64>().copied() {
             Ok((integer + 1).into())
         } else {
@@ -1209,8 +1220,11 @@ fn 
callback_errors_preserve_message_and_add_object_context() {
             any_object_pointer(expected)
         );
     }
+}
 
-    // The failing node may be a pre-order replacement or a post-order rebuilt 
parent.
+// The failing node may be a pre-order replacement or a post-order rebuilt 
parent.
+#[test]
+fn map_errors_name_the_replaced_or_rebuilt_node() {
     for order in [WalkOrder::PreOrder, WalkOrder::PostOrder] {
         let root = Array::from_vec(vec![0i64]);
         let mut failed_node = None;

Reply via email to