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 f135303b [Rust] Extend match_any with scalars and typed mutation views 
(#899)
f135303b is described below

commit f135303be857de59a3acac84abb0dc85c192c0ca
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Nov 2 20:58:34 2026 -0500

    [Rust] Extend match_any with scalars and typed mutation views (#899)
    
    Match payloads in `Any`, `AnyView`, object references and `MutationView`
    with explicit result types: `Type(value)`, borrowed `NodeObj(ref node)`,
    and `MutationView<Type>(capability)`. Inputs are taken by value once;
    use `&value` to retain the owner.
    
    Typed arms match strict runtime categories and preserve stored numeric
    values, with ordinary Rust aliases, qualified types, guards and an
    ordered fallback. Ordinary `Map<K, V>` arms are supported; typed
    mutation capabilities containing Maps remain outside the supported
    scope.
---
 rust/tvm-ffi-macros/src/lib.rs                  |  21 +-
 rust/tvm-ffi-macros/src/match_any.rs            | 565 +++++-------------------
 rust/tvm-ffi-macros/src/object_macros.rs        |   2 +
 rust/tvm-ffi/src/any.rs                         |  25 --
 rust/tvm-ffi/src/collections/array.rs           |  12 +
 rust/tvm-ffi/src/collections/list.rs            |   6 +
 rust/tvm-ffi/src/collections/map.rs             |  13 +-
 rust/tvm-ffi/src/extra/unchanged.rs             |   4 +
 rust/tvm-ffi/src/match_any_internal.rs          | 385 ++++++++++++----
 rust/tvm-ffi/src/type_traits.rs                 |  40 ++
 rust/tvm-ffi/tests/test_match_any.rs            | 307 ++++++++++++-
 rust/tvm-ffi/tests/test_match_any_ast_lookup.rs |  67 +--
 rust/tvm-ffi/tests/test_structural_mutate.rs    |  12 +
 13 files changed, 854 insertions(+), 605 deletions(-)

diff --git a/rust/tvm-ffi-macros/src/lib.rs b/rust/tvm-ffi-macros/src/lib.rs
index 44cabbdc..ce81c24d 100644
--- a/rust/tvm-ffi-macros/src/lib.rs
+++ b/rust/tvm-ffi-macros/src/lib.rs
@@ -39,20 +39,19 @@ pub fn dispatch(attr: TokenStream, item: TokenStream) -> 
TokenStream {
     dispatch::dispatch(attr, item)
 }
 
-/// Match object-backed values carried by an Any-compatible scrutinee.
+/// Match payloads in `Any`, `AnyView`, object references or `MutationView`.
 ///
-/// The scrutinee may be an owned object handle, `Any`, or `AnyView`. Convert 
an
-/// already-borrowed object handle to `AnyView` before invoking the macro.
+/// Write `Type(value)` to bind an owned or scalar result, `NodeObj(ref node)`
+/// to borrow an object node, or `MutationView<Type>(capability)` to transfer a
+/// mutation capability. Rust type aliases and qualified types are accepted.
+/// Arms are tried in order; end with an unguarded `_ => ...` fallback.
 ///
-/// Typed arms are checked conversions, not native Rust destructuring.
-/// `Handle(value)` converts to an owning handle. `NodeType(ref node)` borrows
-/// an `ObjectCore` node without acquiring ownership; the binding is 
`&NodeType`.
-/// For owning or custom matcher types, `Matcher(ref value)` retains the 
existing
-/// conversion and borrows its local result. Shared node matching cannot grant
-/// mutable access, and bindings remain bounded by the scrutinee/view borrow.
-/// Guards are evaluated in source order before selecting an arm.
+/// The input is evaluated and taken by value once. Use `&value` to retain its
+/// owner. Matching is strict: it does not coerce between value categories or
+/// truncate stored numeric values. Guards may reject a match and try the next 
arm.
 ///
-/// Non-object values skip the typed patterns and use the `_` fallback.
+/// Typed mutation capabilities do not support Map payloads, including nested
+/// Maps; use `MutationView<Any>` for those. Ordinary `Map<K, V>` arms are 
supported.
 #[proc_macro_error]
 #[proc_macro]
 pub fn match_any(input: TokenStream) -> TokenStream {
diff --git a/rust/tvm-ffi-macros/src/match_any.rs 
b/rust/tvm-ffi-macros/src/match_any.rs
index 07640948..3522af8d 100644
--- a/rust/tvm-ffi-macros/src/match_any.rs
+++ b/rust/tvm-ffi-macros/src/match_any.rs
@@ -17,10 +17,10 @@
  * under the License.
  */
 
-use proc_macro2::{Ident, Span, TokenStream};
+use proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree};
 use quote::quote;
 use syn::parse::{Parse, ParseStream};
-use syn::{braced, parenthesized, Expr, Pat, Path, Result, Token};
+use syn::{braced, Expr, Pat, Result, Token, Type};
 
 use crate::utils::get_tvm_ffi_crate;
 
@@ -34,7 +34,7 @@ struct MatchAnyInput {
 }
 
 struct TypedArm {
-    matcher: Path,
+    matcher: Type,
     binding: Pat,
     guard: Option<Expr>,
     body: Expr,
@@ -61,13 +61,22 @@ impl Parse for MatchAnyInput {
                 content.parse::<Token![=>]>()?;
                 fallback = Some(content.parse::<Expr>()?);
             } else {
-                let matcher = content.parse::<Path>()?;
-                let binding_content;
-                parenthesized!(binding_content in content);
-                let binding = binding_content.parse::<Pat>()?;
-                if !binding_content.is_empty() {
-                    return Err(binding_content.error("expected one binding 
pattern"));
+                // The last parenthesized group is the binding, so unit, 
pointer,
+                // qualified and generic Rust types retain their ordinary 
syntax.
+                let mut pattern = Vec::new();
+                while !content.is_empty() && !content.peek(Token![if]) && 
!content.peek(Token![=>])
+                {
+                    pattern.push(content.parse::<TokenTree>()?);
                 }
+                let binding = match pattern.pop() {
+                    Some(TokenTree::Group(group))
+                        if group.delimiter() == Delimiter::Parenthesis =>
+                    {
+                        syn::parse2::<Pat>(group.stream())?
+                    }
+                    _ => return Err(content.error("expected `Type(binding)`")),
+                };
+                let matcher = 
syn::parse2::<Type>(pattern.into_iter().collect())?;
                 let guard = if content.peek(Token![if]) {
                     content.parse::<Token![if]>()?;
                     Some(content.parse::<Expr>()?)
@@ -108,113 +117,100 @@ pub fn expand(input: proc_macro::TokenStream) -> 
proc_macro::TokenStream {
 
 fn expand_match_any(input: MatchAnyInput) -> TokenStream {
     let tvm_ffi = get_tvm_ffi_crate();
+    let span = Span::mixed_site();
+    let source = Ident::new("__tvm_ffi_match_any_source", span);
+    let probe = Ident::new("__tvm_ffi_match_any_source_probe", span);
+    let view = Ident::new("__tvm_ffi_match_any_view", span);
+    let lookup = Ident::new("__tvm_ffi_match_any_lookup", span);
     let scrutinee = input.scrutinee;
     let fallback = input.fallback;
     let arms = input.arms;
-    let can_attempt_leaf_lookup = arms.len() >= MIN_LOOKUP_TABLE_ARMS
+    let can_lookup = arms.len() >= MIN_LOOKUP_TABLE_ARMS
         && arms
             .iter()
             .all(|arm| arm.guard.is_none() && is_simple_binding(&arm.binding));
-
-    if can_attempt_leaf_lookup {
-        expand_leaf_lookup_match(&tvm_ffi, &scrutinee, &arms, &fallback)
-    } else {
-        expand_ordered_match(&tvm_ffi, &scrutinee, &arms, &fallback)
-    }
-}
-
-fn expand_ordered_match(
-    tvm_ffi: &TokenStream,
-    scrutinee: &Expr,
-    arms: &[TypedArm],
-    fallback: &Expr,
-) -> TokenStream {
-    let span = Span::mixed_site();
-    let source = Ident::new("__tvm_ffi_match_any_source", span);
-    let converted = Ident::new("__tvm_ffi_match_any_converted", span);
-    let view = Ident::new("__tvm_ffi_match_any_view", span);
-    let rejected = Ident::new("__tvm_ffi_match_any_rejected", span);
-    let dispatch = expand_ordered_dispatch(tvm_ffi, arms, fallback, &view, 
&rejected);
-
-    quote! {
-        {
-            let #source = &(#scrutinee);
-            let #converted: ::core::result::Result<
-                #tvm_ffi::AnyView<'_>,
-                ::core::convert::Infallible,
-            > = 
::core::convert::TryInto::<#tvm_ffi::AnyView<'_>>::try_into(#source);
-            let #view = match #converted {
-                ::core::result::Result::Ok(view) => view,
-                ::core::result::Result::Err(error) => match error {},
+    let lookup_setup = if can_lookup {
+        let table = expand_leaf_table_lookup(&tvm_ffi, &arms, &view);
+        quote! {
+            let #lookup = {
+                let #view = 
#tvm_ffi::match_any_internal::SourceView::view(&#source);
+                if #view.type_index() >= 
#tvm_ffi::TypeIndex::kTVMFFIStaticObjectBegin as i32 {
+                    #table
+                } else { ::core::result::Result::Err(()) }
             };
-            if #view.type_index()
-                >= #tvm_ffi::TypeIndex::kTVMFFIStaticObjectBegin as i32
-            {
-                #dispatch
-            } else {
-                #fallback
-            }
         }
-    }
-}
-
-fn expand_ordered_dispatch(
-    tvm_ffi: &TokenStream,
-    arms: &[TypedArm],
-    fallback: &Expr,
-    view: &Ident,
-    rejected: &Ident,
-) -> TokenStream {
-    expand_ordered_try_into_chain(
-        tvm_ffi,
-        arms,
-        quote!({ #fallback }),
-        view,
-        rejected,
-        |_, arm| {
-            let binding = &arm.binding;
-            let body = &arm.body;
-            if let Some(guard) = &arm.guard {
-                quote!(::core::result::Result::Ok(#binding) if #guard => { 
#body })
-            } else {
-                quote!(::core::result::Result::Ok(#binding) => { #body })
-            }
-        },
-    )
-}
-
-fn expand_ordered_try_into_chain<F>(
-    tvm_ffi: &TokenStream,
-    arms: &[TypedArm],
-    fallback: TokenStream,
-    view: &Ident,
-    rejected: &Ident,
-    mut matched_arm: F,
-) -> TokenStream
-where
-    F: FnMut(usize, &TypedArm) -> TokenStream,
-{
-    arms.iter()
-        .enumerate()
-        .rev()
-        .fold(fallback, |next, (arm_id, arm)| {
-            if let Some(binding) = shared_ref_binding(&arm.binding) {
-                return expand_ref_pattern_arm(tvm_ffi, arm, binding, view, 
next);
+    } else {
+        quote!()
+    };
+    let dispatch = arms.iter().enumerate().rev().fold(quote!({ #fallback }), 
|next, (id, arm)| {
+        let id = id as u32;
+        let matcher = &arm.matcher;
+        let binding = &arm.binding;
+        let body = &arm.body;
+        let guard = arm.guard.as_ref().map(|guard| quote!(if #guard));
+        let conversion = if shared_ref_binding(binding).is_some() {
+            quote!({
+                use #tvm_ffi::match_any_internal::RefPatternConversion as _;
+                let probe = 
#tvm_ffi::match_any_internal::PatternConversionProbe::<#matcher>::new();
+                (&&&probe).try_convert_ref(&mut #source)
+            })
+        } else {
+            quote!(<#matcher as 
#tvm_ffi::match_any_internal::MatchPattern<_>>::try_match(&mut #source))
+        };
+        let conversion = if can_lookup {
+            quote!(if #lookup.is_err() || #lookup == 
::core::result::Result::Ok(::core::option::Option::Some(#id)) {
+                #conversion
+            } else { ::core::result::Result::Err(()) })
+        } else { conversion };
+        let rejected = Ident::new("__tvm_ffi_match_any_rejected", span);
+        let recovered = Ident::new("__tvm_ffi_match_any_recovered", span);
+        let recover = quote! {
+            if let ::core::result::Result::Ok(#recovered) = 
#rejected.map(#tvm_ffi::match_any_internal::Matched::recover) {
+                #tvm_ffi::match_any_internal::Restore::restore(&mut #source, 
#recovered);
             }
-            let matcher = &arm.matcher;
-            let matched = matched_arm(arm_id, arm);
-            let conversion = expand_pattern_conversion(tvm_ffi, matcher, view);
-
+        };
+        if let Some(binding) = shared_ref_binding(binding) {
+            let holder = Ident::new("__tvm_ffi_match_any_ref_holder", span);
+            let converted = Ident::new("__tvm_ffi_match_any_ref_converted", 
span);
+            let accepted = Ident::new("__tvm_ffi_match_any_ref_accepted", 
span);
+            let test_guard = arm.guard.as_ref().map(|guard| 
quote!(#guard)).unwrap_or_else(|| quote!(true));
+            quote! {{
+                let #converted = #conversion;
+                let #accepted = if let ::core::result::Result::Ok(#holder) = 
&#converted {
+                    #[allow(unused_variables)]
+                    let #binding: &#matcher = 
::core::borrow::Borrow::<#matcher>::borrow(&#holder.value);
+                    #test_guard
+                } else { false };
+                if #accepted {
+                    let #holder = #converted.as_ref().unwrap();
+                    #[allow(unused_variables)]
+                    let #binding: &#matcher = 
::core::borrow::Borrow::<#matcher>::borrow(&#holder.value);
+                    #body
+                } else {
+                    let #rejected = #converted;
+                    #recover
+                    #next
+                }
+            }}
+        } else {
             quote! {
                 match #conversion {
-                    #matched,
+                    
::core::result::Result::Ok(#tvm_ffi::match_any_internal::Matched { value: 
#binding, .. }) #guard => { #body },
                     #rejected => {
-                        ::core::mem::drop(#rejected);
+                        #recover
                         #next
                     }
                 }
             }
-        })
+        }
+    });
+    quote! {{
+        use #tvm_ffi::match_any_internal::PrepareSource as _;
+        let mut #probe = 
#tvm_ffi::match_any_internal::SourceProbe::new(#scrutinee);
+        let mut #source = #probe.prepare();
+        #lookup_setup
+        #dispatch
+    }}
 }
 
 fn shared_ref_binding(binding: &Pat) -> Option<&Ident> {
@@ -230,108 +226,11 @@ fn shared_ref_binding(binding: &Pat) -> Option<&Ident> {
     }
 }
 
-fn expand_ref_pattern_arm(
-    tvm_ffi: &TokenStream,
-    arm: &TypedArm,
-    binding: &Ident,
-    view: &Ident,
-    next: TokenStream,
-) -> TokenStream {
-    let holder = Ident::new("__tvm_ffi_match_any_ref_holder", 
Span::mixed_site());
-    let matcher = &arm.matcher;
-    let body = &arm.body;
-    let borrow = quote! {
-        #[allow(unused_variables)]
-        let #binding: &#matcher = 
::core::borrow::Borrow::<#matcher>::borrow(&#holder);
-    };
-    let conversion = expand_ref_pattern_conversion(tvm_ffi, matcher, view);
-    if let Some(guard) = &arm.guard {
-        let converted = Ident::new("__tvm_ffi_match_any_ref_converted", 
Span::mixed_site());
-        let accepted = Ident::new("__tvm_ffi_match_any_ref_accepted", 
Span::mixed_site());
-        // Keep the guard binding out of the fallthrough scope. Preserve native
-        // guard control flow and emit the remaining arms only once.
-        quote! {{
-            let #converted = #conversion;
-            let #accepted = if let ::core::result::Result::Ok(#holder) = 
&#converted {
-                #[allow(unused_variables)]
-                let #binding: &#matcher = 
::core::borrow::Borrow::<#matcher>::borrow(#holder);
-                #guard
-            } else {
-                false
-            };
-            if #accepted {
-                let #holder = #converted.as_ref().unwrap();
-                #[allow(unused_variables)]
-                let #binding: &#matcher = 
::core::borrow::Borrow::<#matcher>::borrow(#holder);
-                #body
-            } else {
-                ::core::mem::drop(#converted);
-                #next
-            }
-        }}
-    } else {
-        quote! {
-            if let ::core::result::Result::Ok(#holder) = #conversion {
-                #borrow
-                #body
-            } else {
-                #next
-            }
-        }
-    }
-}
-
-fn expand_ref_pattern_conversion(
-    tvm_ffi: &TokenStream,
-    matcher: &Path,
-    view: &Ident,
-) -> TokenStream {
-    let probe = Ident::new("__tvm_ffi_match_any_ref_probe", 
Span::mixed_site());
-    quote! {{
-        use #tvm_ffi::match_any_internal::RefPatternConversion as _;
-        let #probe = 
#tvm_ffi::match_any_internal::PatternConversionProbe::<#matcher>::new();
-        (&&&#probe).try_convert_ref(&#view)
-    }}
-}
-
-fn expand_pattern_conversion(tvm_ffi: &TokenStream, matcher: &Path, view: 
&Ident) -> TokenStream {
-    let span = Span::mixed_site();
-    let probe = Ident::new("__tvm_ffi_match_any_conversion_probe", span);
-    let converted = Ident::new("__tvm_ffi_match_any_pattern_conversion", span);
-
-    quote! {
-        {
-            use #tvm_ffi::match_any_internal::PatternConversion as _;
-
-            let #probe =
-                
#tvm_ffi::match_any_internal::PatternConversionProbe::<#matcher>::new();
-            let #converted: ::core::result::Result<#matcher, ()> =
-                (&#probe).try_convert(#view);
-            #converted
-        }
-    }
-}
-
-fn expand_exact_pattern_conversion(
-    tvm_ffi: &TokenStream,
-    matcher: &Path,
-    view: &Ident,
-) -> TokenStream {
-    let span = Span::mixed_site();
-    let probe = Ident::new("__tvm_ffi_match_any_conversion_probe", span);
-    let converted = Ident::new("__tvm_ffi_match_any_pattern_conversion", span);
-
-    quote! {
-        {
-            use #tvm_ffi::match_any_internal::PatternConversion as _;
-
-            let #probe =
-                
#tvm_ffi::match_any_internal::PatternConversionProbe::<#matcher>::new();
-            let #converted: ::core::result::Result<#matcher, ()> = unsafe {
-                (&#probe).try_convert_after_exact_match(#view)
-            };
-            #converted
-        }
+fn is_simple_binding(binding: &Pat) -> bool {
+    match binding {
+        Pat::Ident(binding) => binding.subpat.is_none(),
+        Pat::Wild(_) => true,
+        _ => false,
     }
 }
 
@@ -349,260 +248,30 @@ fn expand_leaf_table_lookup(tvm_ffi: &TokenStream, arms: 
&[TypedArm], view: &Ide
             let matcher = &arm.matcher;
             let metadata = if shared_ref_binding(&arm.binding).is_some() {
                 quote!({
-                    use #tvm_ffi::match_any_internal::RefPatternConversion as 
_;
+                    use #tvm_ffi::match_any_internal::RefPatternMetadata as _;
                     let probe = 
#tvm_ffi::match_any_internal::PatternConversionProbe::<#matcher>::new();
                     (&&&probe).leaf_pattern()
                 })
             } else {
-                quote!(::core::marker::PhantomData::<#matcher>)
+                
quote!(::core::marker::PhantomData::<#tvm_ffi::match_any_internal::StrictLeaf<#matcher>>)
             };
             quote!(#tail.prepend(#metadata))
         },
     );
-
-    quote! {
-        {
-            use #tvm_ffi::match_any_internal::LeafPatternMetadata as _;
-
-            let #probe =
-                #pattern_probe;
-            match (&#probe).leaf_pattern_list_id() {
-                ::core::option::Option::Some(#pattern_list_id) => {
-                    static #static_table: ::std::sync::OnceLock<
-                        #tvm_ffi::match_any_internal::LeafLookupTable,
-                    > = ::std::sync::OnceLock::new();
-                    let #table = #static_table.get_or_init(|| {
-                        let mut #type_indices = [0_i32; #arm_count];
-                        (&#probe).fill_leaf_type_indices(&mut #type_indices);
-                        #tvm_ffi::match_any_internal::LeafLookupTable::build(
-                            #pattern_list_id,
-                            &#type_indices,
-                        )
-                    });
-                    #table.lookup(#pattern_list_id, #view.type_index())
-                }
-                ::core::option::Option::None => {
-                    ::core::result::Result::Err(())
-                }
-            }
-        }
-    }
-}
-
-// The identifiers are the hygienic names the generated code shares with its
-// caller.
-#[allow(clippy::too_many_arguments)]
-fn expand_direct_leaf_selection(
-    tvm_ffi: &TokenStream,
-    arms: &[TypedArm],
-    arm_constants: &[Ident],
-    arm_variants: &[Ident],
-    arm_id: &Ident,
-    view: &Ident,
-    rejected: &Ident,
-    selected_enum: &Ident,
-    selected_value: &Ident,
-) -> TokenStream {
-    let selections = arms.iter().enumerate().map(|(arm_id, arm)| {
-        let matcher = &arm.matcher;
-        let variant = &arm_variants[arm_id];
-        let arm_constant = &arm_constants[arm_id];
-        let conversion = if shared_ref_binding(&arm.binding).is_some() {
-            expand_ref_pattern_conversion(tvm_ffi, matcher, view)
-        } else {
-            expand_exact_pattern_conversion(tvm_ffi, matcher, view)
-        };
-
-        quote! {
-            #arm_constant => {
-                match #conversion {
-                    ::core::result::Result::Ok(#selected_value) => {
-                        #selected_enum::#variant(#selected_value)
-                    }
-                    #rejected => {
-                        ::core::mem::drop(#rejected);
-                        ::core::panic!(
-                            "match_any! leaf lookup selected an incompatible 
arm"
-                        )
-                    }
-                }
-            }
-        }
-    });
-
-    quote! {
-        match #arm_id {
-            #(#selections,)*
-            _ => ::core::unreachable!(),
-        }
-    }
-}
-
-fn expand_leaf_body_dispatch(
-    arms: &[TypedArm],
-    arm_variants: &[Ident],
-    selected_enum: &Ident,
-    selected: &Ident,
-    fallback_variant: &Ident,
-    fallback: &Expr,
-) -> TokenStream {
-    let body_arms = arms.iter().enumerate().map(|(arm_id, arm)| {
-        let binding = &arm.binding;
-        let body = &arm.body;
-        let variant = &arm_variants[arm_id];
-        if let Some(binding) = shared_ref_binding(binding) {
-            let holder = Ident::new("__tvm_ffi_match_any_ref_holder", 
Span::mixed_site());
-            let matcher = &arm.matcher;
-            return quote! {
-                #selected_enum::#variant(#holder) => {
-                    let #binding: &#matcher = 
::core::borrow::Borrow::<#matcher>::borrow(&#holder);
-                    #body
-                }
-            };
-        }
-
-        quote! {
-            #selected_enum::#variant(#binding) => {
-                #body
-            }
-        }
-    });
-
-    quote! {
-        match #selected {
-            #(#body_arms,)*
-            #selected_enum::#fallback_variant => {
-                #fallback
-            }
-        }
-    }
-}
-
-fn expand_leaf_lookup_match(
-    tvm_ffi: &TokenStream,
-    scrutinee: &Expr,
-    arms: &[TypedArm],
-    fallback: &Expr,
-) -> TokenStream {
-    let span = Span::mixed_site();
-    let source = Ident::new("__tvm_ffi_match_any_source", span);
-    let converted = Ident::new("__tvm_ffi_match_any_converted", span);
-    let view = Ident::new("__tvm_ffi_match_any_view", span);
-    let rejected = Ident::new("__tvm_ffi_match_any_rejected", span);
-    let arm_id = Ident::new("__tvm_ffi_match_any_arm_id", span);
-    let selected = Ident::new("__tvm_ffi_match_any_selected", span);
-    let selected_value = Ident::new("__tvm_ffi_match_any_selected_value", 
span);
-    let selected_enum = Ident::new("__TvmFfiMatchAnyArm", span);
-    let fallback_variant = Ident::new("Fallback", span);
-    let arm_count = arms.len();
-    let arm_types = (0..arm_count)
-        .map(|arm_id| Ident::new(&format!("__TvmFfiMatchAnyType{arm_id}"), 
span))
-        .collect::<Vec<_>>();
-    let arm_variants = (0..arm_count)
-        .map(|arm_id| Ident::new(&format!("Arm{arm_id}"), span))
-        .collect::<Vec<_>>();
-    let arm_constants = (0..arm_count)
-        .map(|arm_id| Ident::new(&format!("__TVM_FFI_MATCH_ANY_ARM_{arm_id}"), 
span))
-        .collect::<Vec<_>>();
-    let arm_constant_definitions =
-        arm_constants
-            .iter()
-            .enumerate()
-            .map(|(arm_id, arm_constant)| {
-                quote! {
-                    const #arm_constant: #tvm_ffi::match_any_internal::ArmId =
-                        #arm_id as #tvm_ffi::match_any_internal::ArmId;
-                }
-            });
-    let lookup_arm_id = expand_leaf_table_lookup(tvm_ffi, arms, &view);
-    let ordered_selection = arms.iter().enumerate().rev().fold(
-        quote!(#selected_enum::#fallback_variant),
-        |next, (arm_id, arm)| {
-            let variant = &arm_variants[arm_id];
-            let conversion = if shared_ref_binding(&arm.binding).is_some() {
-                expand_ref_pattern_conversion(tvm_ffi, &arm.matcher, &view)
-            } else {
-                expand_pattern_conversion(tvm_ffi, &arm.matcher, &view)
-            };
-            quote! {
-                if let ::core::result::Result::Ok(#selected_value) = 
#conversion {
-                    #selected_enum::#variant(#selected_value)
-                } else {
-                    #next
-                }
-            }
-        },
-    );
-
-    let direct_selection = expand_direct_leaf_selection(
-        tvm_ffi,
-        arms,
-        &arm_constants,
-        &arm_variants,
-        &arm_id,
-        &view,
-        &rejected,
-        &selected_enum,
-        &selected_value,
-    );
-    let body_dispatch = expand_leaf_body_dispatch(
-        arms,
-        &arm_variants,
-        &selected_enum,
-        &selected,
-        &fallback_variant,
-        fallback,
-    );
-
-    quote! {
-        {
-            enum #selected_enum<#(#arm_types),*> {
-                #(#arm_variants(#arm_types),)*
-                #fallback_variant,
+    quote! {{
+        use #tvm_ffi::match_any_internal::LeafPatternMetadata as _;
+        let #probe = #pattern_probe;
+        match (&#probe).leaf_pattern_list_id() {
+            ::core::option::Option::Some(#pattern_list_id) => {
+                static #static_table: 
::std::sync::OnceLock<#tvm_ffi::match_any_internal::LeafLookupTable> = 
::std::sync::OnceLock::new();
+                let #table = #static_table.get_or_init(|| {
+                    let mut #type_indices = [0_i32; #arm_count];
+                    (&#probe).fill_leaf_type_indices(&mut #type_indices);
+                    
#tvm_ffi::match_any_internal::LeafLookupTable::build(#pattern_list_id, 
&#type_indices)
+                });
+                #table.lookup(#pattern_list_id, #view.type_index())
             }
-
-            #(#arm_constant_definitions)*
-
-            let #source = &(#scrutinee);
-            let #converted: ::core::result::Result<
-                #tvm_ffi::AnyView<'_>,
-                ::core::convert::Infallible,
-            > = 
::core::convert::TryInto::<#tvm_ffi::AnyView<'_>>::try_into(#source);
-            let #view = match #converted {
-                ::core::result::Result::Ok(view) => view,
-                ::core::result::Result::Err(error) => match error {},
-            };
-            let #selected =
-                if #view.type_index()
-                    >= #tvm_ffi::TypeIndex::kTVMFFIStaticObjectBegin as i32
-                {
-                    match #lookup_arm_id {
-                        ::core::result::Result::Ok(
-                            ::core::option::Option::Some(#arm_id),
-                        ) => {
-                            #direct_selection
-                        }
-                        ::core::result::Result::Ok(
-                            ::core::option::Option::None,
-                        ) => {
-                            #selected_enum::#fallback_variant
-                        }
-                        ::core::result::Result::Err(()) => {
-                            #ordered_selection
-                        }
-                    }
-                } else {
-                    #selected_enum::#fallback_variant
-                };
-            #body_dispatch
+            ::core::option::Option::None => ::core::result::Result::Err(()),
         }
-    }
-}
-
-fn is_simple_binding(binding: &Pat) -> bool {
-    match binding {
-        Pat::Ident(binding) => binding.subpat.is_none(),
-        Pat::Wild(_) => true,
-        _ => false,
-    }
+    }}
 }
diff --git a/rust/tvm-ffi-macros/src/object_macros.rs 
b/rust/tvm-ffi-macros/src/object_macros.rs
index 408b1dcc..46c6ea34 100644
--- a/rust/tvm-ffi-macros/src/object_macros.rs
+++ b/rust/tvm-ffi-macros/src/object_macros.rs
@@ -563,6 +563,8 @@ pub(crate) fn expand_object_ref(
                 <ContainerType as 
#tvm_ffi_crate::object::ObjectCore>::TYPE_FINAL
             };
 
+            const MATCH_ANY_STRICT_EXACT: bool = Self::MATCH_ANY_EXACT;
+
             #[inline]
             fn match_any_exact_type_index() -> i32 {
                 type ContainerType = <#struct_name as 
#tvm_ffi_crate::object::ObjectRefCore>
diff --git a/rust/tvm-ffi/src/any.rs b/rust/tvm-ffi/src/any.rs
index bb90dfd7..5f0efdcc 100644
--- a/rust/tvm-ffi/src/any.rs
+++ b/rust/tvm-ffi/src/any.rs
@@ -317,31 +317,6 @@ impl Drop for Any {
     }
 }
 
-/// Convert an [`AnyView`] without constructing a diagnostic error on mismatch.
-#[inline]
-pub(crate) fn try_cast_from_any_view<T>(value: &AnyView<'_>) -> Result<T, ()>
-where
-    T: AnyCompatible,
-{
-    unsafe { T::try_cast_from_any_view(&value.data) }
-}
-
-/// Copy a value after exact-leaf lookup has established compatibility.
-///
-/// # Safety
-///
-/// `T::MATCH_ANY_EXACT` must be true and `value.type_index()` must equal
-/// `T::match_any_exact_type_index()`.
-#[inline(always)]
-pub(crate) unsafe fn copy_from_any_view_after_check<T>(value: &AnyView<'_>) -> 
T
-where
-    T: AnyCompatible,
-{
-    debug_assert!(T::MATCH_ANY_EXACT);
-    debug_assert!(T::check_any_strict(&value.data));
-    T::copy_from_any_view_after_check(&value.data)
-}
-
 // convert Any ref to AnyView
 impl<'a> From<&'a Any> for AnyView<'a> {
     #[inline]
diff --git a/rust/tvm-ffi/src/collections/array.rs 
b/rust/tvm-ffi/src/collections/array.rs
index 59f025ef..83bc032a 100644
--- a/rust/tvm-ffi/src/collections/array.rs
+++ b/rust/tvm-ffi/src/collections/array.rs
@@ -271,6 +271,18 @@ where
         true
     }
 
+    unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+        let container = &*(data.data_union.v_obj as *const ArrayObj);
+        let base_ptr = container.data as *const TVMFFIAny;
+        for i in 0..container.size {
+            let elem_any = &*base_ptr.add(i as usize);
+            if !T::container_match_constraints(elem_any) {
+                return false;
+            }
+        }
+        true
+    }
+
     unsafe fn copy_to_any_view(src: &Self, data: &mut TVMFFIAny) {
         data.type_index = TypeIndex::kTVMFFIArray as i32;
         data.data_union.v_obj = ObjectArc::as_raw(Self::data(src)) as *mut 
TVMFFIObject;
diff --git a/rust/tvm-ffi/src/collections/list.rs 
b/rust/tvm-ffi/src/collections/list.rs
index 63aad17d..87c5b0f6 100644
--- a/rust/tvm-ffi/src/collections/list.rs
+++ b/rust/tvm-ffi/src/collections/list.rs
@@ -584,6 +584,12 @@ unsafe impl<T: ContainerElement> AnyCompatible for List<T> 
{
                 .all(|cell| T::container_check_any_strict(cell))
     }
 
+    unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+        seq_cells(data)
+            .iter()
+            .all(|cell| T::container_match_constraints(cell))
+    }
+
     unsafe fn copy_to_any_view(src: &Self, data: &mut TVMFFIAny) {
         data.type_index = TypeIndex::kTVMFFIList as i32;
         data.data_union.v_obj = ObjectArc::as_raw(Self::data(src)) as *mut 
TVMFFIObject;
diff --git a/rust/tvm-ffi/src/collections/map.rs 
b/rust/tvm-ffi/src/collections/map.rs
index 0f320a47..f96b83f9 100644
--- a/rust/tvm-ffi/src/collections/map.rs
+++ b/rust/tvm-ffi/src/collections/map.rs
@@ -291,7 +291,7 @@ where
 
     /// Reads all entries as raw `(Any, Any)` pairs without converting to
     /// `K`/`V`, propagating FFI failures instead of panicking (unlike the
-    /// iterator API): this backs `check_any_strict` and
+    /// iterator API): this backs strict checks and the converting fallback in
     /// `try_cast_from_any_view`, which run during argument decoding where a
     /// panic could unwind across the C ABI.
     fn try_raw_entries(&self) -> Result<Vec<(Any, Any)>> {
@@ -496,6 +496,17 @@ where
         }
     }
 
+    unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+        let map = <Self as 
AnyCompatible>::copy_from_any_view_after_check(data);
+        match map.try_raw_entries() {
+            Ok(entries) => entries.iter().all(|(k, v)| unsafe {
+                K::container_match_constraints(k.as_raw_ffi_any())
+                    && V::container_match_constraints(v.as_raw_ffi_any())
+            }),
+            Err(_) => false,
+        }
+    }
+
     unsafe fn copy_to_any_view(src: &Self, data: &mut TVMFFIAny) {
         data.type_index = TypeIndex::kTVMFFIMap as i32;
         data.data_union.v_obj = ObjectArc::as_raw(Self::data(src)) as *mut 
TVMFFIObject;
diff --git a/rust/tvm-ffi/src/extra/unchanged.rs 
b/rust/tvm-ffi/src/extra/unchanged.rs
index 0ebdccad..e36d6ddf 100644
--- a/rust/tvm-ffi/src/extra/unchanged.rs
+++ b/rust/tvm-ffi/src/extra/unchanged.rs
@@ -246,6 +246,10 @@ unsafe impl<T: ContainerElement> AnyCompatible for 
UnchangedOr<T> {
         }
     }
 
+    unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+        Unchanged::check_any_strict(data) || 
T::container_match_constraints(data)
+    }
+
     unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> Self {
         if Unchanged::check_any_strict(data) {
             return Self::unchanged();
diff --git a/rust/tvm-ffi/src/match_any_internal.rs 
b/rust/tvm-ffi/src/match_any_internal.rs
index d89ad994..c5fd11c6 100644
--- a/rust/tvm-ffi/src/match_any_internal.rs
+++ b/rust/tvm-ffi/src/match_any_internal.rs
@@ -28,122 +28,268 @@ use crate::{AnyCompatible, AnyView};
 #[doc(hidden)]
 pub type ArmId = u32;
 
-/// Conversion adapter used by `match_any!` typed arms.
+impl<'a, T> From<&'a crate::MutationView<'_, T>> for AnyView<'a> {
+    #[inline(always)]
+    fn from(value: &'a crate::MutationView<'_, T>) -> Self {
+        value.as_any_view()
+    }
+}
+
+/// Own the scrutinee before selecting its source adapter.
 #[doc(hidden)]
-pub struct PatternConversionProbe<T>(PhantomData<fn() -> T>);
+pub struct SourceProbe<T>(Option<T>);
+impl<T> SourceProbe<T> {
+    #[inline(always)]
+    pub fn new(value: T) -> Self {
+        Self(Some(value))
+    }
+}
 
-impl<T> PatternConversionProbe<T> {
-    #[doc(hidden)]
-    pub const fn new() -> Self {
-        Self(PhantomData)
+#[doc(hidden)]
+pub struct OwnedSource(crate::Any);
+#[doc(hidden)]
+pub struct ViewSource<'a>(AnyView<'a>);
+#[doc(hidden)]
+pub struct CapabilitySource<'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.
+#[doc(hidden)]
+pub trait PrepareSource {
+    type Source;
+    fn prepare(&mut self) -> Self::Source;
+}
+impl<T: crate::ObjectRefCore + AnyCompatible> PrepareSource for SourceProbe<T> 
{
+    type Source = OwnedSource;
+    #[inline(always)]
+    fn prepare(&mut self) -> Self::Source {
+        OwnedSource(self.0.take().unwrap().into())
+    }
+}
+impl SourceProbe<crate::Any> {
+    #[inline(always)]
+    pub fn prepare(&mut self) -> OwnedSource {
+        OwnedSource(self.0.take().unwrap())
+    }
+}
+impl<'a> SourceProbe<AnyView<'a>> {
+    #[inline(always)]
+    pub fn prepare(&mut self) -> ViewSource<'a> {
+        ViewSource(self.0.take().unwrap())
+    }
+}
+impl<'a, T: ?Sized> SourceProbe<&'a T> {
+    #[inline(always)]
+    pub fn prepare<'out>(&mut self) -> ViewSource<'out>
+    where
+        AnyView<'out>: From<&'a T>,
+    {
+        ViewSource(self.0.take().unwrap().into())
+    }
+}
+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()))
     }
 }
 
-/// Prefer the lightweight `AnyCompatible` conversion while retaining a
-/// `TryInto` fallback for custom matcher types.
 #[doc(hidden)]
-pub trait PatternConversion<'a, T> {
-    #[doc(hidden)]
-    fn try_convert(&self, view: AnyView<'a>) -> Result<T, ()>;
-
-    /// Convert after exact-leaf lookup has established that `view` matches
-    /// `T`. Custom `TryInto` matchers retain their checked conversion.
-    ///
-    /// # Safety
-    ///
-    /// The caller must establish the `AnyCompatible::MATCH_ANY_EXACT`
-    /// contract before using the unchecked implementation.
-    #[doc(hidden)]
-    unsafe fn try_convert_after_exact_match(&self, view: AnyView<'a>) -> 
Result<T, ()> {
-        self.try_convert(view)
+pub trait SourceView {
+    fn view(&self) -> AnyView<'_>;
+}
+impl SourceView for OwnedSource {
+    #[inline(always)]
+    fn view(&self) -> AnyView<'_> {
+        (&self.0).into()
+    }
+}
+impl SourceView for ViewSource<'_> {
+    #[inline(always)]
+    fn view(&self) -> AnyView<'_> {
+        self.0
+    }
+}
+impl SourceView for CapabilitySource<'_> {
+    #[inline(always)]
+    fn view(&self) -> AnyView<'_> {
+        self.0.as_ref().unwrap().as_any_view()
     }
 }
 
-impl<'a, T: AnyCompatible> PatternConversion<'a, T> for 
PatternConversionProbe<T> {
+/// A rejected guard drops an ordinary result or returns the original 
capability.
+/// There is no Drop implementation, so native match guards retain Rust's usual
+/// restriction against moving their bindings before the guard succeeds.
+#[doc(hidden)]
+pub struct Matched<T, R> {
+    pub value: T,
+    recover: fn(T) -> R,
+}
+impl<T, R> Matched<T, R> {
+    #[inline(always)]
+    pub fn recover(self) -> R {
+        (self.recover)(self.value)
+    }
+}
+#[doc(hidden)]
+pub trait Restore<R> {
+    fn restore(&mut self, recovery: R);
+}
+impl<S> Restore<()> for S {
+    #[inline(always)]
+    fn restore(&mut self, _: ()) {}
+}
+impl<'a> Restore<crate::MutationView<'a>> for CapabilitySource<'a> {
     #[inline(always)]
-    fn try_convert(&self, view: AnyView<'a>) -> Result<T, ()> {
-        if T::MATCH_ANY_EXACT {
-            if view.type_index() == T::match_any_exact_type_index() {
-                Ok(unsafe { 
crate::any::copy_from_any_view_after_check::<T>(&view) })
+    fn restore(&mut self, recovery: crate::MutationView<'a>) {
+        debug_assert!(self.0.is_none());
+        self.0 = Some(recovery);
+    }
+}
+
+/// Type-directed matching. The source parameter also expresses whether an
+/// aliased result can retain the input lifetime or transfer its capability.
+#[doc(hidden)]
+pub trait MatchPattern<S>: Sized {
+    type Recovery;
+    fn try_match(source: S) -> Result<Matched<Self, Self::Recovery>, ()>;
+}
+impl<'b, T: crate::type_traits::ContainerElement, S: SourceView> 
MatchPattern<&'b mut S> for T {
+    type Recovery = ();
+    #[inline(always)]
+    fn try_match(source: &'b mut S) -> Result<Matched<Self, ()>, ()> {
+        let view = source.view();
+        let data = view.as_raw_ffi_any();
+        unsafe {
+            if T::container_check_any_strict(data) && 
T::container_match_constraints(data) {
+                Ok(Matched {
+                    value: T::container_copy_from_any_view_after_check(data),
+                    recover: drop,
+                })
             } else {
                 Err(())
             }
-        } else {
-            crate::any::try_cast_from_any_view::<T>(&view)
         }
     }
-
+}
+impl<'a, 'b, 'out> MatchPattern<&'b mut ViewSource<'a>> for AnyView<'out>
+where
+    'a: 'out,
+{
+    type Recovery = ();
     #[inline(always)]
-    unsafe fn try_convert_after_exact_match(&self, view: AnyView<'a>) -> 
Result<T, ()> {
-        Ok(crate::any::copy_from_any_view_after_check::<T>(&view))
+    fn try_match(source: &'b mut ViewSource<'a>) -> Result<Matched<Self, ()>, 
()> {
+        Ok(Matched {
+            value: source.0,
+            recover: drop,
+        })
     }
 }
-
-impl<'a, T> PatternConversion<'a, T> for &PatternConversionProbe<T>
-where
-    AnyView<'a>: TryInto<T>,
+impl<'b> MatchPattern<&'b mut OwnedSource> for AnyView<'b> {
+    type Recovery = ();
+    #[inline(always)]
+    fn try_match(source: &'b mut OwnedSource) -> Result<Matched<Self, ()>, ()> 
{
+        Ok(Matched {
+            value: source.view(),
+            recover: drop,
+        })
+    }
+}
+impl<'a, 'b> MatchPattern<&'b mut CapabilitySource<'a>> for AnyView<'b> {
+    type Recovery = ();
+    #[inline(always)]
+    fn try_match(source: &'b mut CapabilitySource<'a>) -> Result<Matched<Self, 
()>, ()> {
+        Ok(Matched {
+            value: source.view(),
+            recover: drop,
+        })
+    }
+}
+impl<'a, 'b, T: crate::type_traits::ContainerElement> MatchPattern<&'b mut 
CapabilitySource<'a>>
+    for crate::MutationView<'a, T>
 {
+    type Recovery = crate::MutationView<'a>;
     #[inline(always)]
-    fn try_convert(&self, view: AnyView<'a>) -> Result<T, ()> {
-        view.try_into().map_err(|_| ())
+    fn try_match(
+        source: &'b mut CapabilitySource<'a>,
+    ) -> Result<Matched<Self, Self::Recovery>, ()> {
+        match source.0.take().unwrap().try_cast::<T>() {
+            Ok(value) => {
+                if unsafe { 
T::container_match_constraints(value.as_any_view().as_raw_ffi_any()) } {
+                    Ok(Matched {
+                        value,
+                        recover: crate::MutationView::into_untyped,
+                    })
+                } else {
+                    source.0 = Some(value.into_untyped());
+                    Err(())
+                }
+            }
+            Err(value) => {
+                source.0 = Some(value);
+                Err(())
+            }
+        }
     }
 }
 
-/// Conversion for a shared `ref` binding, borrowing object nodes while 
retaining
-/// the ordinary owning conversion for object handles and custom matchers.
 #[doc(hidden)]
-pub trait RefPatternConversion<'view, 'value, T> {
+pub struct PatternConversionProbe<T>(PhantomData<fn() -> T>);
+impl<T> PatternConversionProbe<T> {
     #[doc(hidden)]
-    type LeafPattern;
+    pub const fn new() -> Self {
+        Self(PhantomData)
+    }
+}
 
-    #[doc(hidden)]
+#[doc(hidden)]
+pub trait RefPatternMetadata {
+    type LeafPattern;
     fn leaf_pattern(&self) -> PhantomData<Self::LeafPattern> {
         PhantomData
     }
+}
+impl<T: crate::object::ObjectCore> RefPatternMetadata for 
&&PatternConversionProbe<T> {
+    type LeafPattern = BorrowedLeaf<T>;
+}
+impl<T> RefPatternMetadata for &PatternConversionProbe<T> {
+    type LeafPattern = StrictLeaf<T>;
+}
 
-    #[doc(hidden)]
+#[doc(hidden)]
+pub trait RefPatternConversion<'b, S, T> {
     type Holder: std::borrow::Borrow<T>;
-
-    #[doc(hidden)]
-    fn try_convert_ref(&self, view: &'view AnyView<'value>) -> 
Result<Self::Holder, ()>;
+    type Recovery;
+    fn try_convert_ref(
+        &self,
+        source: &'b mut S,
+    ) -> Result<Matched<Self::Holder, Self::Recovery>, ()>;
 }
-
-// The macro starts at three references. Autoderef selects the first applicable
-// implementation: borrowed ObjectCore, AnyCompatible, then custom TryInto.
-impl<'view, 'value, T: crate::object::ObjectCore> RefPatternConversion<'view, 
'value, T>
+impl<'b, T: crate::object::ObjectCore, S: SourceView> RefPatternConversion<'b, 
S, T>
     for &&PatternConversionProbe<T>
 {
-    type LeafPattern = BorrowedLeaf<T>;
-    type Holder = &'view T;
-
+    type Holder = &'b T;
+    type Recovery = ();
     #[inline(always)]
-    fn try_convert_ref(&self, view: &'view AnyView<'value>) -> 
Result<Self::Holder, ()> {
-        view.downcast_ref::<T>().ok_or(())
+    fn try_convert_ref(&self, source: &'b mut S) -> 
Result<Matched<Self::Holder, ()>, ()> {
+        let view = source.view();
+        let node = view.downcast_ref::<T>().ok_or(())? as *const T;
+        // SAFETY: the checked node is borrowed from source for 'b. No owning
+        // conversion or capability transfer can occur while this borrow lives.
+        Ok(Matched {
+            value: unsafe { &*node },
+            recover: drop,
+        })
     }
 }
-
-impl<'view, 'value, T: AnyCompatible> RefPatternConversion<'view, 'value, T>
+impl<'b, S: 'b, T: MatchPattern<&'b mut S>> RefPatternConversion<'b, S, T>
     for &PatternConversionProbe<T>
 {
-    type LeafPattern = T;
     type Holder = T;
-
+    type Recovery = T::Recovery;
     #[inline(always)]
-    fn try_convert_ref(&self, view: &'view AnyView<'value>) -> 
Result<Self::Holder, ()> {
-        (*self).try_convert(*view)
-    }
-}
-
-impl<'view, 'value, T> RefPatternConversion<'view, 'value, T> for 
PatternConversionProbe<T>
-where
-    AnyView<'value>: TryInto<T>,
-{
-    type LeafPattern = T;
-    type Holder = T;
-
-    #[inline(always)]
-    fn try_convert_ref(&self, view: &'view AnyView<'value>) -> 
Result<Self::Holder, ()> {
-        (*view).try_into().map_err(|_| ())
+    fn try_convert_ref(&self, source: &'b mut S) -> Result<Matched<T, 
Self::Recovery>, ()> {
+        T::try_match(source)
     }
 }
 
@@ -215,18 +361,33 @@ impl LeafLookupTable {
 }
 
 /// Type-level list used to collect leaf object-pattern metadata.
+/// Its cache identity uses final object representations, so matcher lifetimes
+/// never need to be static. Unknown generic/custom types use the probe 
fallback.
 #[doc(hidden)]
-pub trait LeafPatternList: 'static {
+pub trait LeafPatternList {
+    #[doc(hidden)]
+    type Key: 'static;
+
     #[doc(hidden)]
     const ALL_EXACT_LEAF: bool;
 
+    /// Validate that the final payload identity describes this exact matcher.
+    #[doc(hidden)]
+    fn matches_key() -> bool;
+
     #[doc(hidden)]
     fn fill_leaf_type_indices(out: &mut [i32]);
 }
 
 impl LeafPatternList for () {
+    type Key = ();
     const ALL_EXACT_LEAF: bool = true;
 
+    #[inline(always)]
+    fn matches_key() -> bool {
+        true
+    }
+
     #[inline(always)]
     fn fill_leaf_type_indices(out: &mut [i32]) {
         debug_assert!(out.is_empty());
@@ -235,10 +396,23 @@ impl LeafPatternList for () {
 
 impl<Head, Tail> LeafPatternList for (Head, Tail)
 where
-    Head: AnyCompatible + 'static,
+    Head: AnyCompatible + crate::object::ObjectRefCore,
     Tail: LeafPatternList,
 {
-    const ALL_EXACT_LEAF: bool = Head::MATCH_ANY_EXACT && Tail::ALL_EXACT_LEAF;
+    type Key = (
+        <Head as crate::object::ObjectRefCore>::ContainerType,
+        Tail::Key,
+    );
+    const ALL_EXACT_LEAF: bool = Head::MATCH_ANY_EXACT
+        && <Head::ContainerType as crate::object::ObjectCore>::TYPE_FINAL
+        && Tail::ALL_EXACT_LEAF;
+
+    #[inline(always)]
+    fn matches_key() -> bool {
+        Head::match_any_exact_type_index()
+            == <Head::ContainerType as crate::object::ObjectCore>::type_index()
+            && Tail::matches_key()
+    }
 
     #[inline(always)]
     fn fill_leaf_type_indices(out: &mut [i32]) {
@@ -250,6 +424,53 @@ where
     }
 }
 
+/// Strict matching metadata is independent of coercive conversion metadata.
+#[doc(hidden)]
+pub struct StrictLeaf<T>(PhantomData<fn() -> T>);
+
+impl<Head, Tail> LeafPatternList for (StrictLeaf<Head>, Tail)
+where
+    Head: AnyCompatible + crate::object::ObjectRefCore,
+    Tail: LeafPatternList,
+{
+    type Key = (
+        <Head as crate::object::ObjectRefCore>::ContainerType,
+        Tail::Key,
+    );
+    const ALL_EXACT_LEAF: bool = Head::MATCH_ANY_STRICT_EXACT
+        && <Head::ContainerType as crate::object::ObjectCore>::TYPE_FINAL
+        && Tail::ALL_EXACT_LEAF;
+
+    #[inline(always)]
+    fn matches_key() -> bool {
+        Head::match_any_exact_type_index()
+            == <Head::ContainerType as crate::object::ObjectCore>::type_index()
+            && Tail::matches_key()
+    }
+
+    #[inline(always)]
+    fn fill_leaf_type_indices(out: &mut [i32]) {
+        let (head, tail) = out.split_first_mut().expect("missing leaf pattern 
slot");
+        *head = Head::match_any_exact_type_index();
+        Tail::fill_leaf_type_indices(tail);
+    }
+}
+
+impl<'a, Head, Tail> LeafPatternList for (StrictLeaf<crate::MutationView<'a, 
Head>>, Tail)
+where
+    Head: AnyCompatible + crate::object::ObjectRefCore,
+    Tail: LeafPatternList,
+{
+    type Key = <(StrictLeaf<Head>, Tail) as LeafPatternList>::Key;
+    const ALL_EXACT_LEAF: bool = <(StrictLeaf<Head>, Tail) as 
LeafPatternList>::ALL_EXACT_LEAF;
+    fn matches_key() -> bool {
+        <(StrictLeaf<Head>, Tail) as LeafPatternList>::matches_key()
+    }
+    fn fill_leaf_type_indices(out: &mut [i32]) {
+        <(StrictLeaf<Head>, Tail) as 
LeafPatternList>::fill_leaf_type_indices(out);
+    }
+}
+
 /// Lifetime-free metadata for a borrowed object node pattern.
 #[doc(hidden)]
 pub struct BorrowedLeaf<T>(PhantomData<fn() -> T>);
@@ -257,8 +478,14 @@ pub struct BorrowedLeaf<T>(PhantomData<fn() -> T>);
 impl<Head: crate::object::ObjectCore, Tail: LeafPatternList> LeafPatternList
     for (BorrowedLeaf<Head>, Tail)
 {
+    type Key = (Head, Tail::Key);
     const ALL_EXACT_LEAF: bool = Head::TYPE_FINAL && Tail::ALL_EXACT_LEAF;
 
+    #[inline(always)]
+    fn matches_key() -> bool {
+        Tail::matches_key()
+    }
+
     #[inline(always)]
     fn fill_leaf_type_indices(out: &mut [i32]) {
         let (head, tail) = out.split_first_mut().expect("missing leaf pattern 
slot");
@@ -300,7 +527,7 @@ impl<T> LeafPatternMetadata for &LeafPatternProbe<T> {}
 impl<T: LeafPatternList> LeafPatternMetadata for LeafPatternProbe<T> {
     #[inline(always)]
     fn leaf_pattern_list_id(&self) -> Option<TypeId> {
-        T::ALL_EXACT_LEAF.then(TypeId::of::<T>)
+        (T::ALL_EXACT_LEAF && T::matches_key()).then(TypeId::of::<T::Key>)
     }
 
     #[inline(always)]
diff --git a/rust/tvm-ffi/src/type_traits.rs b/rust/tvm-ffi/src/type_traits.rs
index 0e3abeaf..7f6bef87 100644
--- a/rust/tvm-ffi/src/type_traits.rs
+++ b/rust/tvm-ffi/src/type_traits.rs
@@ -37,6 +37,14 @@ pub unsafe trait AnyCompatible: Sized {
     #[doc(hidden)]
     const MATCH_ANY_EXACT: bool = false;
 
+    /// Whether strict matching accepts exactly `match_any_exact_type_index()`.
+    /// Unlike `MATCH_ANY_EXACT`, this covers every tag, including scalars:
+    /// `check_any_strict` and `match_constraints` together must succeed if and
+    /// only if the index matches.
+    /// Container-element checks must have the same acceptance set.
+    #[doc(hidden)]
+    const MATCH_ANY_STRICT_EXACT: bool = false;
+
     /// Return the sole runtime object type index accepted by this conversion.
     #[doc(hidden)]
     fn match_any_exact_type_index() -> i32 {
@@ -74,6 +82,16 @@ pub unsafe trait AnyCompatible: Sized {
     // check if the value is compatible with the type
     unsafe fn check_any_strict(data: &TVMFFIAny) -> bool;
 
+    /// Additional value-preservation checks used only by `match_any!`, after
+    /// `check_any_strict` succeeds. Ordinary conversion APIs are unchanged.
+    ///
+    /// # Safety
+    /// `data` must have passed `Self::check_any_strict`.
+    #[doc(hidden)]
+    unsafe fn match_constraints(_data: &TVMFFIAny) -> bool {
+        true
+    }
+
     /// Copy value from TVMFFIAny after checking
     /// caller must ensure that the value is compatible with the type
     unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> Self;
@@ -209,6 +227,7 @@ mod container_element_ops {
         unsafe fn container_copy_to_any_view(src: &Self, data: &mut TVMFFIAny);
         unsafe fn container_move_to_any(src: Self, data: &mut TVMFFIAny);
         unsafe fn container_check_any_strict(data: &TVMFFIAny) -> bool;
+        unsafe fn container_match_constraints(data: &TVMFFIAny) -> bool;
         unsafe fn container_copy_from_any_view_after_check(data: &TVMFFIAny) 
-> Self;
         unsafe fn container_move_from_any_after_check(data: &mut TVMFFIAny) -> 
Self;
         unsafe fn container_try_cast_from_any_view(data: &TVMFFIAny) -> 
Result<Self, ()>;
@@ -232,6 +251,10 @@ mod container_element_ops {
         unsafe fn container_check_any_strict(data: &TVMFFIAny) -> bool {
             <T as AnyCompatible>::check_any_strict(data)
         }
+        #[inline]
+        unsafe fn container_match_constraints(data: &TVMFFIAny) -> bool {
+            <T as AnyCompatible>::match_constraints(data)
+        }
 
         #[inline]
         unsafe fn container_copy_from_any_view_after_check(data: &TVMFFIAny) 
-> Self {
@@ -281,6 +304,10 @@ mod container_element_ops {
         unsafe fn container_check_any_strict(_data: &TVMFFIAny) -> bool {
             true
         }
+        #[inline]
+        unsafe fn container_match_constraints(_data: &TVMFFIAny) -> bool {
+            true
+        }
 
         #[inline]
         unsafe fn container_copy_from_any_view_after_check(data: &TVMFFIAny) 
-> Self {
@@ -373,6 +400,10 @@ macro_rules! impl_any_compatible_for_int {
                     data.type_index == TypeIndex::kTVMFFIInt as i32
                 }
 
+                unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+                    <$int_type>::try_from(data.data_union.v_int64).is_ok()
+                }
+
                 unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> 
Self {
                     data.data_union.v_int64 as $int_type
                 }
@@ -450,6 +481,10 @@ unsafe impl<T: AnyCompatible> AnyCompatible for Option<T> {
         return T::check_any_strict(data) || data.type_index == 
TypeIndex::kTVMFFINone as i32;
     }
 
+    unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+        data.type_index == TypeIndex::kTVMFFINone as i32 || 
T::match_constraints(data)
+    }
+
     unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> Self {
         if data.type_index == TypeIndex::kTVMFFINone as i32 {
             None
@@ -534,6 +569,11 @@ macro_rules! impl_any_compatible_for_float {
                     data.type_index == TypeIndex::kTVMFFIFloat as i32
                 }
 
+                unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
+                    let value = data.data_union.v_float64;
+                    ((value as $float_type) as f64).to_bits() == 
value.to_bits()
+                }
+
                 unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> 
Self {
                     data.data_union.v_float64 as $float_type
                 }
diff --git a/rust/tvm-ffi/tests/test_match_any.rs 
b/rust/tvm-ffi/tests/test_match_any.rs
index bcc8d025..d3906a37 100644
--- a/rust/tvm-ffi/tests/test_match_any.rs
+++ b/rust/tvm-ffi/tests/test_match_any.rs
@@ -22,15 +22,7 @@ use std::any::TypeId;
 use tvm_ffi::match_any_internal::{ArmId, LeafLookupTable, LeafPatternMetadata, 
LeafPatternProbe};
 use tvm_ffi::{match_any, Any, AnyView, Array, Function, Map, Module, Shape, 
Tensor, TypeIndex};
 
-struct CustomModuleMatcher;
-
-impl<'a> TryFrom<AnyView<'a>> for CustomModuleMatcher {
-    type Error = &'static str;
-
-    fn try_from(value: AnyView<'a>) -> Result<Self, Self::Error> {
-        value.try_as::<Module>().map(|_| Self).ok_or("not a Module")
-    }
-}
+type CustomModuleMatcher = Module;
 
 #[test]
 fn matches_concrete_object_containers_in_source_order() {
@@ -77,7 +69,7 @@ fn matches_concrete_object_containers_in_source_order() {
     let source = Array::new(vec![1_i64, 2, 3]);
     let count = || ObjectArc::strong_count(<Array<i64> as 
ObjectRefCore>::data(&source));
     let size = match_any! {
-        source {
+        &source {
             Array::<i64>(ref handle) if {
                 assert_eq!(count(), 2);
                 assert_eq!(handle.len(), 3);
@@ -100,7 +92,7 @@ fn matches_concrete_object_containers_in_source_order() {
     assert_eq!(size, 3);
     assert_eq!(count(), 1);
     let size = match_any! {
-        source {
+        &source {
             Array::<i64>(ref handle) => {
                 let _: &Array<i64> = handle;
                 assert_eq!(count(), 2);
@@ -114,7 +106,7 @@ fn matches_concrete_object_containers_in_source_order() {
     let mut saved = None;
     assert_eq!(
         match_any! {
-            source {
+            &source {
                 Array::<i64>(ref handle) if { saved = Some(handle); true } => 
saved.unwrap().len(),
                 _ => 0,
             }
@@ -124,17 +116,175 @@ fn matches_concrete_object_containers_in_source_order() {
     let node = 7;
     assert_eq!(
         match_any! {
-            source {
+            &source {
                 ArrayObj(ref node) if node.size == 0 => 0,
                 _ => node,
             }
         },
         7
     );
+
+    // Matching distinguishes runtime categories and rejects numeric 
truncation.
+    let mut evaluations = 0;
+    let mut guards = 0;
+    assert_eq!(
+        match_any!({ evaluations += 1; Any::from(true) } {
+            i64(_) if { guards += 1; true } => 0,
+            f64(_) => 0,
+            bool(n) if { guards += 1; !n } => 0,
+            bool(n) => i32::from(n),
+            _ => 0,
+        }),
+        1
+    );
+    assert_eq!((evaluations, guards), (1, 1));
+    assert_eq!(
+        match_any!(Any::from(1.25_f64) { f32(n) => n, _ => 0.0 }),
+        1.25
+    );
+    for (stored, unsigned, signed) in [
+        (-129_i64, None, None),
+        (-128, None, Some(-128)),
+        (127, Some(127), Some(127)),
+        (128, Some(128), None),
+        (255, Some(255), None),
+        (256, None, None),
+    ] {
+        assert_eq!(
+            match_any!(Any::from(stored) { u8(n) => Some(n), _ => None }),
+            unsigned
+        );
+        assert_eq!(
+            match_any!(Any::from(stored) { i8(n) => Some(n), _ => None }),
+            signed
+        );
+    }
+    assert_eq!(
+        match_any!(Any::from(i64::MAX) { u64(n) => Some(n), _ => None }),
+        Some(i64::MAX as u64)
+    );
+    assert_eq!(
+        match_any!(Any::from(u64::MAX) { u64(_) => unreachable!(), i64(n) => 
n, _ => 0 }),
+        -1
+    );
+    for (stored, expected) in [
+        (-0.0, Some(0x8000_0000)),
+        (f64::INFINITY, Some(f32::INFINITY.to_bits())),
+        (f32::from_bits(0xffc0_0001) as f64, Some(0xffc0_0001)),
+        (f64::from_bits(0x7ff8_0000_0000_0001), None),
+        (16_777_217.0, None),
+        (1e40, None),
+    ] {
+        assert_eq!(
+            match_any!(Any::from(stored) {
+                f32(n) => Some(n.to_bits()),
+                f64(n) => { assert_eq!(n.to_bits(), stored.to_bits()); None },
+                _ => unreachable!(),
+            }),
+            expected
+        );
+    }
+    assert_eq!(
+        match_any!(Any::from(257_i64) { Option<u8>(n) => n, _ => None }),
+        None
+    );
+    assert_eq!(
+        match_any!(Any::from(()) { Option<u8>(n) => Some(n), _ => None }),
+        Some(None)
+    );
+
+    assert!(match_any!(Any::from(true) { bool(ref n) => *n, _ => false }));
+    assert!(match_any!(Any::from(()) { ()(()) => true, _ => false }));
+    let pointer = core::ptr::null_mut::<core::ffi::c_void>();
+    assert!(
+        match_any!(Any::from(pointer) { *mut core::ffi::c_void(p) => 
p.is_null(), _ => false })
+    );
+    trait Payload {
+        type Item;
+    }
+    struct Integer;
+    impl Payload for Integer {
+        type Item = i64;
+    }
+    assert_eq!(
+        match_any!(Any::from(7_i64) { <Integer as Payload>::Item(n) => n, _ => 
0 }),
+        7
+    );
+    fn identity<'a>(view: AnyView<'a>) -> AnyView<'a> {
+        match_any!(view { AnyView::<'_>(rest) => rest, _ => unreachable!() })
+    }
+    assert_eq!(
+        identity(AnyView::from(&source)).debug_strong_count(),
+        Some(1)
+    );
+
+    use tvm_ffi::{InplaceMode, MutationView};
+    let mut capability_evaluations = 0;
+    let capability = match_any!({
+        capability_evaluations += 1;
+        MutationView::borrowed(AnyView::from(&source))
+    } {
+        tvm_ffi::MutationView<Array<f64>>(_) => unreachable!(),
+        tvm_ffi::MutationView<Array<i64>>(matched) if {
+            assert_eq!(matched.inplace_mode(), InplaceMode::Disallow);
+            assert_eq!(count(), 1);
+            false
+        } => unreachable!(),
+        Array<i64>(owned) if {
+            assert_eq!(owned.len(), 3);
+            assert_eq!(count(), 2);
+            false
+        } => unreachable!(),
+        ArrayObj(ref node) if { assert_eq!(count(), 1); node.size == 0 } => 
unreachable!(),
+        AnyView::<'_>(view) if { assert_eq!(view.debug_strong_count(), 
Some(1)); false } => unreachable!(),
+        tvm_ffi::MutationView<Any>(rest) => rest,
+        _ => unreachable!(),
+    });
+    assert_eq!(capability_evaluations, 1);
+    assert_eq!(count(), 1);
+    assert_eq!(capability.inplace_mode(), InplaceMode::Disallow);
+    assert_eq!(
+        match_any!(&capability { ArrayObj(ref node) => node.size, _ => 0 }),
+        3
+    );
+
+    let typed = match_any!(capability {
+        tvm_ffi::MutationView<Array<i64>>(array) => array,
+        _ => unreachable!(),
+    });
+    assert_eq!(typed.as_any_view().debug_strong_count(), Some(1));
+    // Already narrowed inputs are normalized before attempts and guard 
recovery.
+    assert_eq!(
+        match_any!(typed {
+            tvm_ffi::MutationView<Array<f64>>(_) => 0,
+            ArrayObj(ref node) => node.size,
+            _ => 0,
+        }),
+        3
+    );
+    assert!(match_any!(MutationView::borrowed(AnyView::from(&())) {
+        tvm_ffi::MutationView<()>(_unit) => true, _ => false,
+    }));
+
+    fn native_control_flow(value: AnyView<'_>) -> Result<i64, ()> {
+        for _ in 0..1 {
+            match_any!(value {
+                i64(n) if { if n < 0 { return Err(()); } true } => return 
Ok(n),
+                bool(_) => continue,
+                _ => break,
+            });
+        }
+        let n = match_any!(value { f64(_) => Err(())?, _ => 0 });
+        Ok(n)
+    }
+    assert_eq!(native_control_flow(AnyView::from(&7_i64)), Ok(7));
+    assert_eq!(native_control_flow(AnyView::from(&-1_i64)), Err(()));
+    assert_eq!(native_control_flow(AnyView::from(&true)), Ok(0));
+    assert_eq!(native_control_flow(AnyView::from(&1.0_f64)), Err(()));
 }
 
 #[test]
-fn custom_try_into_matcher_keeps_ordered_compatibility() {
+fn type_alias_matcher_keeps_strict_compatibility() {
     fn matches(value: AnyView<'_>) -> bool {
         match_any! {
             value {
@@ -177,6 +327,52 @@ fn 
parameterized_containers_use_complete_conversion_semantics() {
     };
 
     assert_eq!(selected, "float array");
+    use tvm_ffi::{List, MutationView};
+    let values = Array::new(vec![257_i64]);
+    assert_eq!(
+        match_any!(&values { Array<u8>(_) => 0, Array<i64>(_) => 1, _ => 2 }),
+        1
+    );
+    assert!(!match_any!(Array::new(vec![true]) { Array<i64>(_) => true, _ => 
false }));
+    assert!(!match_any!(&values { List<i64>(_) => true, _ => false }));
+    let list = [257_i64].into_iter().collect::<List<i64>>();
+    assert!(!match_any!(&list { Array<i64>(_) => true, List<u8>(_) => true, _ 
=> false }));
+    let nested = Array::new(vec![Array::new(vec![Some(257_i64)])]);
+    assert_eq!(
+        match_any!(&nested {
+            Array<Array<Option<u8>>>(_) => 0,
+            Array<Array<Option<i64>>>(_) => 1,
+            _ => 2,
+        }),
+        1
+    );
+    let map = [(1_i64, values)]
+        .into_iter()
+        .collect::<Map<i64, Array<i64>>>();
+    assert_eq!(
+        match_any!(&map { Map<u8, Array<u8>>(_) => 0, Map<u8, Array<i64>>(_) 
=> 1, _ => 2 }),
+        1
+    );
+    // Transparent result carriers retain the same recursive numeric checks.
+    use tvm_ffi::{Unchanged, UnchangedOr};
+    assert!(!match_any!(Any::from(257_i64) { UnchangedOr<u8>(_) => true, _ => 
false }));
+    assert!(match_any!(Any::from(Unchanged) { UnchangedOr<u8>(_) => true, _ => 
false }));
+    assert!(!match_any!(MutationView::borrowed(AnyView::from(&nested)) {
+        MutationView<UnchangedOr<Array<Array<Option<u8>>>>>(_) => true,
+        _ => false,
+    }));
+    type Cap<'a, T> = MutationView<'a, T>;
+    let cap = MutationView::borrowed(AnyView::from(&nested));
+    let recovered = match_any!(cap {
+        Cap<Array<Array<Option<u8>>>>(_) => unreachable!(),
+        Cap<Array<Array<Option<i64>>>>(value) if {
+            assert_eq!(value.inplace_mode(), tvm_ffi::InplaceMode::Disallow);
+            false
+        } => unreachable!(),
+        Cap<Any>(value) => value,
+        _ => unreachable!(),
+    });
+    assert_eq!(recovered.as_any_view().debug_strong_count(), Some(1));
 }
 
 #[test]
@@ -228,4 +424,87 @@ fn metadata_only_accepts_exact_leaf_patterns() {
     type Custom = (NoAnyCompatibleMetadata, ());
     let custom = LeafPatternProbe::<Custom>::new();
     assert!((&custom).leaf_pattern_list_id().is_none());
+
+    // Large generic and lifetime-bearing matches must compile without a static
+    // bound; their metadata does not justify a final-object table.
+    fn generic<T: tvm_ffi::AnyCompatible>(view: AnyView<'_>) -> Option<T> {
+        match_any!(view {
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            T(value) => Some(value),
+            _ => None,
+        })
+    }
+    fn generic_cap<T: tvm_ffi::AnyCompatible>(value: 
tvm_ffi::MutationView<'_>) -> bool {
+        match_any!(value {
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            tvm_ffi::MutationView<T>(_) => true,
+            _ => false,
+        })
+    }
+    fn identity<'a>(view: AnyView<'a>) -> AnyView<'a> {
+        match_any!(view {
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            AnyView::<'_>(rest) => rest,
+            _ => unreachable!(),
+        })
+    }
+    assert_eq!(generic::<i64>(identity(AnyView::from(&7_i64))), Some(7));
+    assert_eq!(generic::<bool>(AnyView::from(&7_i64)), None);
+    assert!(generic_cap::<i64>(tvm_ffi::MutationView::borrowed(
+        AnyView::from(&7_i64)
+    )));
 }
diff --git a/rust/tvm-ffi/tests/test_match_any_ast_lookup.rs 
b/rust/tvm-ffi/tests/test_match_any_ast_lookup.rs
index 340d7c51..b422324a 100644
--- a/rust/tvm-ffi/tests/test_match_any_ast_lookup.rs
+++ b/rust/tvm-ffi/tests/test_match_any_ast_lookup.rs
@@ -117,7 +117,7 @@ fn dispatches_representative_ast_leaf_nodes() {
 
     // The ref adapter must expose final-node metadata, including in mixed 
lists.
     use tvm_ffi::match_any_internal::{
-        LeafPatternMetadata, LeafPatternProbe, PatternConversionProbe, 
RefPatternConversion,
+        LeafPatternMetadata, LeafPatternProbe, PatternConversionProbe, 
RefPatternMetadata,
     };
     let node_probe = PatternConversionProbe::<AddExprObj>::new();
     let mixed = LeafPatternProbe::<(SubExpr, 
())>::new().prepend((&&&node_probe).leaf_pattern());
@@ -129,32 +129,39 @@ fn dispatches_representative_ast_leaf_nodes() {
         [AddExprObj::type_index(), SubExprObj::type_index()]
     );
 
-    fn classify(value: Any) -> &'static str {
-        match_any! {
-            value {
-                AddExpr(_) => "add",
-                SubExpr(_) => "sub",
-                MulExpr(_) => "mul",
-                DivExpr(_) => "div",
-                ModExpr(_) => "mod",
-                NegExpr(_) => "neg",
-                CallExpr(_) => "call",
-                LetExpr(_) => "let",
-                IfExpr(_) => "if",
-                TupleExpr(_) => "tuple",
-                TupleGetItemExpr(_) => "tuple_get_item",
-                CastExpr(_) => "cast",
-                LoadExpr(_) => "load",
-                StoreExpr(_) => "store",
-                ForExpr(_) => "for",
-                WhileExpr(_) => "while",
-                SeqExpr(_) => "seq",
-                ReturnExpr(_) => "return",
-                ConstantExpr(_) => "constant",
-                VarExpr(_) => "var",
-                _ => "unsupported",
+    type Owned<T> = T;
+    use tvm_ffi::MutationView;
+    macro_rules! classify_all {
+        ($value:expr; $wrapper:ident) => {
+            match_any! {
+                $value {
+                    $wrapper<AddExpr>(_) => "add",
+                    $wrapper<SubExpr>(_) => "sub",
+                    $wrapper<MulExpr>(_) => "mul",
+                    $wrapper<DivExpr>(_) => "div",
+                    $wrapper<ModExpr>(_) => "mod",
+                    $wrapper<NegExpr>(_) => "neg",
+                    $wrapper<CallExpr>(_) => "call",
+                    $wrapper<LetExpr>(_) => "let",
+                    $wrapper<IfExpr>(_) => "if",
+                    $wrapper<TupleExpr>(_) => "tuple",
+                    $wrapper<TupleGetItemExpr>(_) => "tuple_get_item",
+                    $wrapper<CastExpr>(_) => "cast",
+                    $wrapper<LoadExpr>(_) => "load",
+                    $wrapper<StoreExpr>(_) => "store",
+                    $wrapper<ForExpr>(_) => "for",
+                    $wrapper<WhileExpr>(_) => "while",
+                    $wrapper<SeqExpr>(_) => "seq",
+                    $wrapper<ReturnExpr>(_) => "return",
+                    $wrapper<ConstantExpr>(_) => "constant",
+                    $wrapper<VarExpr>(_) => "var",
+                    _ => "unsupported",
+                }
             }
-        }
+        };
+    }
+    fn classify(value: Any) -> &'static str {
+        classify_all!(value; Owned)
     }
 
     fn checked<T>(_: &T, value: &Any, count: usize, name: &'static str) -> 
&'static str {
@@ -164,7 +171,7 @@ fn dispatches_representative_ast_leaf_nodes() {
 
     fn classify_refs<T: ObjectCore>(value: &Any) -> &'static str {
         match_any! {
-            *value {
+            value {
                 T(ref node) => checked(node, value, 1, "add"),
                 SubExpr(ref handle) => checked(handle, value, 2, "sub"),
                 MulExprObj(ref node) => checked(node, value, 1, "mul"),
@@ -218,6 +225,12 @@ fn dispatches_representative_ast_leaf_nodes() {
             assert_eq!(classify_refs::<AddExprObj>(&value), expected);
             assert_eq!(value.debug_strong_count(), Some(1));
         }
+        assert_eq!(classify_all!(&value; Owned), expected);
+        assert_eq!(
+            
classify_all!(MutationView::borrowed(tvm_ffi::AnyView::from(&value)); 
MutationView),
+            expected
+        );
+        assert_eq!(value.debug_strong_count(), Some(1));
         assert_eq!(classify(value), expected);
     }
 
diff --git a/rust/tvm-ffi/tests/test_structural_mutate.rs 
b/rust/tvm-ffi/tests/test_structural_mutate.rs
index 724e3f17..82c4a8fb 100644
--- a/rust/tvm-ffi/tests/test_structural_mutate.rs
+++ b/rust/tvm-ffi/tests/test_structural_mutate.rs
@@ -570,6 +570,18 @@ fn 
consuming_callbacks_forward_permissions_without_temporary_owners() {
             value: MutationView<'_, Array<Any>>,
             ctx: &mut Mutator,
         ) -> Result<UnchangedOr<Any>> {
+            let mode = value.inplace_mode();
+            let count = value.as_any_view().debug_strong_count();
+            let value = tvm_ffi::match_any!(value {
+                MutationView<FfiString>(_) => unreachable!(),
+                MutationView<Array<Any>>(array) if {
+                    assert_eq!(array.inplace_mode(), mode);
+                    assert_eq!(array.as_any_view().debug_strong_count(), 
count);
+                    false
+                } => unreachable!(),
+                MutationView<Array<Any>>(array) => array,
+                _ => unreachable!(),
+            });
             assert_eq!(ctx.inplace_mode(), value.inplace_mode());
             self.observe(&value);
             ctx.default_mutate_with_mode_result(self, value, self.requested)

Reply via email to