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 82efff9a [Rust] match_any: fewer runtime helpers; check the table key
once (#965)
82efff9a is described below
commit 82efff9a04f842c6224a1abfaa40b85a5603245f
Author: Tianqi Chen <[email protected]>
AuthorDate: Sun Nov 8 10:29:29 2026 -0500
[Rust] match_any: fewer runtime helpers; check the table key once (#965)
Simplify the `match_any!` runtime helpers and make the lookup table pay
its key check once.
- An owned scrutinee stays in its probe and is matched through
`ViewSource`; `OwnedSource` is removed.
- A typed `MutationView` arm aliases the source instead of moving it
out, so a rejected guard has nothing to restore.
`MatchPattern::try_match` returns `Option<Self>`; `Matched`, `Restore`,
the `Recovery` type and `DispatchRecovery` are removed.
- Value arms key the lookup table by their own type, removing
`StrictLeaf` and the hidden `MATCH_ANY_STRICT_EXACT` constant (it always
equaled `MATCH_ANY_EXACT`).
- The table's key check (one type-index load per arm) runs once when the
call site's table is built rather than on every match.
- Remove the unused `UnchangedOr::try_map` and `UnchangedOr::try_cast`.
---
rust/tvm-ffi-macros/src/dispatch.rs | 5 +-
rust/tvm-ffi-macros/src/match_any.rs | 40 ++---
rust/tvm-ffi/src/extra/dispatch.rs | 14 --
rust/tvm-ffi/src/extra/structural_mutate.rs | 14 +-
rust/tvm-ffi/src/extra/unchanged.rs | 76 +--------
rust/tvm-ffi/src/match_any_internal.rs | 220 ++++++---------------------
rust/tvm-ffi/src/object.rs | 1 -
rust/tvm-ffi/src/type_traits.rs | 8 -
rust/tvm-ffi/tests/test_structural_mutate.rs | 4 +-
9 files changed, 82 insertions(+), 300 deletions(-)
diff --git a/rust/tvm-ffi-macros/src/dispatch.rs
b/rust/tvm-ffi-macros/src/dispatch.rs
index f2bbee50..83ffd8d0 100644
--- a/rust/tvm-ffi-macros/src/dispatch.rs
+++ b/rust/tvm-ffi-macros/src/dispatch.rs
@@ -194,11 +194,8 @@ fn expand(item: &ItemImpl, args: &DispatchArgs) ->
syn::Result<TokenStream2> {
&& has_pattern_lifetime(&ty)
{
lifetimes.normalize(&mut ty, None);
- // Fix recovery independently of the arm-local mutable source
borrow.
- let recovery =
- quote!(<#ty as
#tvm_ffi::extra::dispatch::DispatchRecovery<#source>>::Recovery);
generics.make_where_clause().predicates.push(syn::parse_quote!(
- for<#borrow> #ty:
#tvm_ffi::match_any_internal::MatchPattern<&#borrow mut #source, Recovery =
#recovery>
+ for<#borrow> #ty:
#tvm_ffi::match_any_internal::MatchPattern<&#borrow mut #source>
));
}
patterns.push(ty);
diff --git a/rust/tvm-ffi-macros/src/match_any.rs
b/rust/tvm-ffi-macros/src/match_any.rs
index 3522af8d..992bc079 100644
--- a/rust/tvm-ffi-macros/src/match_any.rs
+++ b/rust/tvm-ffi-macros/src/match_any.rs
@@ -160,15 +160,11 @@ fn expand_match_any(input: MatchAnyInput) -> TokenStream {
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 { ::core::option::Option::None })
} 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);
- }
- };
+ // Drop a rejected value before later arms check uniqueness.
+ let drop_rejected = quote!(#[allow(clippy::drop_non_drop)]
::core::mem::drop(#rejected););
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);
@@ -176,28 +172,28 @@ fn expand_match_any(input: MatchAnyInput) -> TokenStream {
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 {
+ let #accepted = if let ::core::option::Option::Some(#holder) =
&#converted {
#[allow(unused_variables)]
- let #binding: &#matcher =
::core::borrow::Borrow::<#matcher>::borrow(&#holder.value);
+ let #binding: &#matcher =
::core::borrow::Borrow::<#matcher>::borrow(#holder);
#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);
+ let #binding: &#matcher =
::core::borrow::Borrow::<#matcher>::borrow(#holder);
#body
} else {
let #rejected = #converted;
- #recover
+ #drop_rejected
#next
}
}}
} else {
quote! {
match #conversion {
-
::core::result::Result::Ok(#tvm_ffi::match_any_internal::Matched { value:
#binding, .. }) #guard => { #body },
+ ::core::option::Option::Some(#binding) #guard => { #body },
#rejected => {
- #recover
+ #drop_rejected
#next
}
}
@@ -253,7 +249,7 @@ fn expand_leaf_table_lookup(tvm_ffi: &TokenStream, arms:
&[TypedArm], view: &Ide
(&&&probe).leaf_pattern()
})
} else {
-
quote!(::core::marker::PhantomData::<#tvm_ffi::match_any_internal::StrictLeaf<#matcher>>)
+ quote!(::core::marker::PhantomData::<#matcher>)
};
quote!(#tail.prepend(#metadata))
},
@@ -263,13 +259,19 @@ fn expand_leaf_table_lookup(tvm_ffi: &TokenStream, arms:
&[TypedArm], view: &Ide
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();
+ // Type indices are process-stable, so the key is checked once.
+ static #static_table:
::std::sync::OnceLock<::core::option::Option<#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)
+ (&#probe).matches_key().then(|| {
+ 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())
+ match #table {
+ ::core::option::Option::Some(#table) =>
#table.lookup(#pattern_list_id, #view.type_index()),
+ ::core::option::Option::None =>
::core::result::Result::Err(()),
+ }
}
::core::option::Option::None => ::core::result::Result::Err(()),
}
diff --git a/rust/tvm-ffi/src/extra/dispatch.rs
b/rust/tvm-ffi/src/extra/dispatch.rs
index d82ad536..378acc34 100644
--- a/rust/tvm-ffi/src/extra/dispatch.rs
+++ b/rust/tvm-ffi/src/extra/dispatch.rs
@@ -56,20 +56,6 @@ impl<'a, T> DispatchInput for crate::MutationView<'a, T> {
type Source = crate::match_any_internal::MutationSource<'a>;
}
-// Generated alias bounds must not make recovery depend on a temporary borrow.
-#[doc(hidden)]
-pub trait DispatchRecovery<S> {
- type Recovery;
-}
-impl<S, T: crate::type_traits::ContainerElement> DispatchRecovery<S> for T {
- type Recovery = ();
-}
-impl<'source, 'value>
DispatchRecovery<crate::match_any_internal::ViewSource<'source>>
- for AnyView<'value>
-{
- type Recovery = ();
-}
-
use std::{borrow::BorrowMut, marker::PhantomData};
/// Inferred selectors for dispatcher normalization.
diff --git a/rust/tvm-ffi/src/extra/structural_mutate.rs
b/rust/tvm-ffi/src/extra/structural_mutate.rs
index 156b50bd..dc80da21 100644
--- a/rust/tvm-ffi/src/extra/structural_mutate.rs
+++ b/rust/tvm-ffi/src/extra/structural_mutate.rs
@@ -358,6 +358,13 @@ impl<'a, T> MutationView<'a, T> {
}
}
+ /// # Safety
+ /// The original must not be used while the alias lives.
+ #[inline(always)]
+ pub(crate) unsafe fn alias(&self) -> MutationView<'a, T> {
+ MutationView::from_raw(self.value, self.mode)
+ }
+
// 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)]
@@ -566,13 +573,6 @@ impl<T: object::ObjectRefCore> MutationView<'_, T> {
}
}
-impl<'source, 'value, T: crate::type_traits::ContainerElement>
-
super::dispatch::DispatchRecovery<crate::match_any_internal::MutationSource<'source>>
- for crate::MutationView<'value, T>
-{
- type Recovery = crate::MutationView<'source>;
-}
-
/// The running structural mutation, passed to each handler.
///
/// A handler that matches a node decides how its children are rewritten: call
diff --git a/rust/tvm-ffi/src/extra/unchanged.rs
b/rust/tvm-ffi/src/extra/unchanged.rs
index bff097a2..5bca9555 100644
--- a/rust/tvm-ffi/src/extra/unchanged.rs
+++ b/rust/tvm-ffi/src/extra/unchanged.rs
@@ -24,7 +24,7 @@ use std::marker::PhantomData;
use super::structural_common::{raw_ffi_any_same_as, structural_error_from_raw};
use crate::any::{Any, AnyView, TryFromTemp};
-use crate::error::{Error, Result, TYPE_ERROR};
+use crate::error::{Error, Result};
use crate::tvm_ffi_sys::{TVMFFIAny, TVMFFITypeIndex};
use crate::type_traits::{AnyCompatible, ContainerElement};
@@ -209,80 +209,6 @@ impl<T: ContainerElement> UnchangedOr<T> {
None => UnchangedOr::unchanged(),
}
}
-
- /// Fallibly convert only the replacement, preserving an unchanged result.
- ///
- /// # Arguments
- ///
- /// * `convert` - Converts the replacement; called only when there is one.
- ///
- /// # Returns
- ///
- /// The converted result.
- ///
- /// # Errors
- ///
- /// Returns the error of `convert` unchanged.
- ///
- /// ```
- /// use tvm_ffi::UnchangedOr;
- /// let result =
UnchangedOr::changed(3_i64).try_map(u32::try_from).unwrap();
- /// assert_eq!(result.into_option(), Some(3_u32));
- /// ```
- ///
- /// See also [`UnchangedOr`].
- #[inline]
- pub fn try_map<U: ContainerElement, E>(
- self,
- convert: impl FnOnce(T) -> std::result::Result<U, E>,
- ) -> std::result::Result<UnchangedOr<U>, E> {
- match self.into_option() {
- Some(value) => convert(value).map(UnchangedOr::changed),
- None => Ok(UnchangedOr::unchanged()),
- }
- }
-
- /// Check a replacement's FFI type without cloning it.
- ///
- /// An unchanged result is compatible with every replacement type. Erased
and
- /// narrowing conversions retain the strict type check of
- /// [`Any::downcast_ref`]. For a
- /// known typed conversion, use `map(Into::into)`.
- ///
- /// # Returns
- ///
- /// The result typed as `UnchangedOr<U>`.
- ///
- /// # Errors
- ///
- /// Returns a `TypeError` if the replacement is not stored as `U`.
- ///
- /// ```
- /// use tvm_ffi::{Any, UnchangedOr};
- /// let erased: UnchangedOr<Any> = 7_i64.into();
- /// assert_eq!(erased.try_cast::<i64>()?.into_option(), Some(7));
- /// # Ok::<(), tvm_ffi::Error>(())
- /// ```
- ///
- /// See also [`UnchangedOr`].
- #[inline]
- pub fn try_cast<U: ContainerElement>(self) -> Result<UnchangedOr<U>> {
- if unsafe {
UnchangedOr::<U>::check_any_strict(self.data.as_raw_ffi_any()) } {
- Ok(UnchangedOr {
- data: self.data,
- _marker: PhantomData,
- })
- } else {
- Err(Error::new(
- TYPE_ERROR,
- &format!(
- "structural mutation result does not match {}",
- U::container_type_str()
- ),
- "",
- ))
- }
- }
}
impl UnchangedOr<Any> {
diff --git a/rust/tvm-ffi/src/match_any_internal.rs
b/rust/tvm-ffi/src/match_any_internal.rs
index 2de5fc2a..cbb6425c 100644
--- a/rust/tvm-ffi/src/match_any_internal.rs
+++ b/rust/tvm-ffi/src/match_any_internal.rs
@@ -45,31 +45,23 @@ impl<T> SourceProbe<T> {
}
}
-#[doc(hidden)]
-pub struct OwnedSource(crate::Any);
#[doc(hidden)]
pub struct ViewSource<'a>(AnyView<'a>);
#[doc(hidden)]
-pub struct MutationSource<'a>(Option<crate::MutationView<'a>>);
+pub struct MutationSource<'a>(crate::MutationView<'a>);
-/// Object references move into an owning Any; inherent adapters preserve view
and
-/// view lifetimes independently of the local holder's lifetime.
+/// An owned scrutinee stays in the probe and is viewed in place.
#[doc(hidden)]
pub trait PrepareSource {
- type Source;
- fn prepare(&mut self) -> Self::Source;
+ fn prepare(&mut self) -> ViewSource<'_>;
}
-impl<T: crate::ObjectRefCore> 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> {
+impl<T> PrepareSource for SourceProbe<T>
+where
+ for<'a> AnyView<'a>: From<&'a T>,
+{
#[inline(always)]
- pub fn prepare(&mut self) -> OwnedSource {
- OwnedSource(self.0.take().unwrap())
+ fn prepare(&mut self) -> ViewSource<'_> {
+ ViewSource(self.0.as_ref().unwrap().into())
}
}
impl<'a> SourceProbe<AnyView<'a>> {
@@ -90,7 +82,7 @@ impl<'a, T: ?Sized> SourceProbe<&'a T> {
impl<'a, T> SourceProbe<crate::MutationView<'a, T>> {
#[inline(always)]
pub fn prepare(&mut self) -> MutationSource<'a> {
- MutationSource(Some(self.0.take().unwrap().into_untyped()))
+ MutationSource(self.0.take().unwrap().into_untyped())
}
}
@@ -100,16 +92,6 @@ pub trait SourceView {
/// The source's own cell, which a reference pattern borrows in place.
fn cell(&self) -> &crate::tvm_ffi_sys::TVMFFIAny;
}
-impl SourceView for OwnedSource {
- #[inline(always)]
- fn view(&self) -> AnyView<'_> {
- (&self.0).into()
- }
- #[inline(always)]
- fn cell(&self) -> &crate::tvm_ffi_sys::TVMFFIAny {
- self.0.as_raw_ffi_any()
- }
-}
impl SourceView for ViewSource<'_> {
#[inline(always)]
fn view(&self) -> AnyView<'_> {
@@ -123,67 +105,29 @@ impl SourceView for ViewSource<'_> {
impl SourceView for MutationSource<'_> {
#[inline(always)]
fn view(&self) -> AnyView<'_> {
- self.0.as_ref().unwrap().as_any_view()
+ self.0.as_any_view()
}
#[inline(always)]
fn cell(&self) -> &crate::tvm_ffi_sys::TVMFFIAny {
- self.0.as_ref().unwrap().cell()
+ self.0.cell()
}
}
-/// 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)]
-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 MutationSource<'a> {
- #[inline(always)]
- 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 view.
+/// Type-directed matching. A matched value never consumes the source: a
+/// typed mutation view aliases it, and the macro never touches the source
+/// after an arm accepts, so a rejected guard needs no recovery.
#[doc(hidden)]
pub trait MatchPattern<S>: Sized {
- type Recovery;
- #[allow(clippy::result_unit_err)]
- fn try_match(source: S) -> Result<Matched<Self, Self::Recovery>, ()>;
+ fn try_match(source: S) -> Option<Self>;
}
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, ()>, ()> {
+ fn try_match(source: &'b mut S) -> Option<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(())
- }
+ (T::container_check_any_strict(data) &&
T::container_match_constraints(data))
+ .then(|| T::container_copy_from_any_view_after_check(data))
}
}
}
@@ -191,58 +135,25 @@ impl<'a, 'b, 'out> MatchPattern<&'b mut ViewSource<'a>>
for AnyView<'out>
where
'a: 'out,
{
- type Recovery = ();
- #[inline(always)]
- fn try_match(source: &'b mut ViewSource<'a>) -> Result<Matched<Self, ()>,
()> {
- Ok(Matched {
- value: source.0,
- recover: drop,
- })
- }
-}
-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,
- })
+ fn try_match(source: &'b mut ViewSource<'a>) -> Option<Self> {
+ Some(source.0)
}
}
impl<'a, 'b> MatchPattern<&'b mut MutationSource<'a>> for AnyView<'b> {
- type Recovery = ();
#[inline(always)]
- fn try_match(source: &'b mut MutationSource<'a>) -> Result<Matched<Self,
()>, ()> {
- Ok(Matched {
- value: source.view(),
- recover: drop,
- })
+ fn try_match(source: &'b mut MutationSource<'a>) -> Option<Self> {
+ Some(source.view())
}
}
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 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()) } {
- Ok(Matched {
- value,
- recover: crate::MutationView::into_untyped,
- })
- } else {
- source.0 = Some(value.into_untyped());
- Err(())
- }
- }
- Err(value) => {
- source.0 = Some(value);
- Err(())
- }
- }
+ fn try_match(source: &'b mut MutationSource<'a>) -> Option<Self> {
+ // SAFETY: the macro-private source is never used after an arm accepts
+ // this view, so the alias stays the only live handle.
+ unsafe { source.0.alias() }.downcast::<T>().ok()
}
}
@@ -266,46 +177,36 @@ impl<T: crate::object::ObjectCore> RefPatternMetadata for
&&PatternConversionPro
type LeafPattern = BorrowedLeaf<T>;
}
impl<T> RefPatternMetadata for &PatternConversionProbe<T> {
- type LeafPattern = StrictLeaf<T>;
+ type LeafPattern = T;
}
#[doc(hidden)]
pub trait RefPatternConversion<'b, S, T> {
type Holder: std::borrow::Borrow<T>;
- type Recovery;
- #[allow(clippy::result_unit_err)]
- fn try_convert_ref(
- &self,
- source: &'b mut S,
- ) -> Result<Matched<Self::Holder, Self::Recovery>, ()>;
+ fn try_convert_ref(&self, source: &'b mut S) -> Option<Self::Holder>;
}
impl<'b, T: crate::type_traits::DowncastRefFromAny + 'static, S: SourceView>
RefPatternConversion<'b, S, T> for &&PatternConversionProbe<T>
{
type Holder = &'b T;
- type Recovery = ();
#[inline(always)]
- fn try_convert_ref(&self, source: &'b mut S) ->
Result<Matched<Self::Holder, ()>, ()> {
+ fn try_convert_ref(&self, source: &'b mut S) -> Option<Self::Holder> {
// Borrow the source's own cell, which lives for 'b: a reference type
// 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;
+ let node = unsafe { T::downcast_ref_from_any(source.cell()) }? as
*const T;
// SAFETY: the checked value is borrowed from source for 'b, and the
arm
// does not modify a list or dict holding it (the `match_any!`
// contract). No owning conversion or view transfer can occur while
this
// borrow lives.
- Ok(Matched {
- value: unsafe { &*node },
- recover: drop,
- })
+ Some(unsafe { &*node })
}
}
impl<'b, S: 'b, T: MatchPattern<&'b mut S>> RefPatternConversion<'b, S, T>
for &PatternConversionProbe<T>
{
type Holder = T;
- type Recovery = T::Recovery;
#[inline(always)]
- fn try_convert_ref(&self, source: &'b mut S) -> Result<Matched<T,
Self::Recovery>, ()> {
+ fn try_convert_ref(&self, source: &'b mut S) -> Option<T> {
T::try_match(source)
}
}
@@ -442,50 +343,19 @@ 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)
+/// A typed mutation view arm routes as its value type.
+impl<'a, Head, Tail> LeafPatternList for (crate::MutationView<'a, 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)]
+ type Key = <(Head, Tail) as LeafPatternList>::Key;
+ const ALL_EXACT_LEAF: bool = <(Head, Tail) as
LeafPatternList>::ALL_EXACT_LEAF;
fn matches_key() -> bool {
- Head::match_any_exact_type_index()
- == <Head::ContainerType as crate::object::ObjectCore>::type_index()
- && Tail::matches_key()
+ <(Head, Tail) as LeafPatternList>::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);
+ <(Head, Tail) as LeafPatternList>::fill_leaf_type_indices(out);
}
}
@@ -536,6 +406,11 @@ pub trait LeafPatternMetadata {
None
}
+ #[doc(hidden)]
+ fn matches_key(&self) -> bool {
+ false
+ }
+
#[doc(hidden)]
fn fill_leaf_type_indices(&self, _out: &mut [i32]) {}
}
@@ -545,7 +420,12 @@ 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 && T::matches_key()).then(TypeId::of::<T::Key>)
+ T::ALL_EXACT_LEAF.then(TypeId::of::<T::Key>)
+ }
+
+ #[inline(always)]
+ fn matches_key(&self) -> bool {
+ T::matches_key()
}
#[inline(always)]
diff --git a/rust/tvm-ffi/src/object.rs b/rust/tvm-ffi/src/object.rs
index c9d4a3ff..10c52b3e 100644
--- a/rust/tvm-ffi/src/object.rs
+++ b/rust/tvm-ffi/src/object.rs
@@ -728,7 +728,6 @@ unsafe impl<T: ObjectRefAnyCompatible> AnyCompatible for T {
// An overridden hook makes the type inexact; a non-final object type
always is.
const MATCH_ANY_EXACT: bool = <T as
ObjectRefAnyCompatible>::MATCH_ANY_EXACT
&& <T::ContainerType as ObjectCore>::TYPE_FINAL;
- const MATCH_ANY_STRICT_EXACT: bool = <T as AnyCompatible>::MATCH_ANY_EXACT;
#[inline]
fn match_any_exact_type_index() -> i32 {
diff --git a/rust/tvm-ffi/src/type_traits.rs b/rust/tvm-ffi/src/type_traits.rs
index ad7fef78..bdcff898 100644
--- a/rust/tvm-ffi/src/type_traits.rs
+++ b/rust/tvm-ffi/src/type_traits.rs
@@ -56,14 +56,6 @@ 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 {
diff --git a/rust/tvm-ffi/tests/test_structural_mutate.rs
b/rust/tvm-ffi/tests/test_structural_mutate.rs
index ae84991e..cd2fb8a0 100644
--- a/rust/tvm-ffi/tests/test_structural_mutate.rs
+++ b/rust/tvm-ffi/tests/test_structural_mutate.rs
@@ -2637,8 +2637,8 @@ fn dispatch_handlers_may_return_typed_results() {
&mut self,
value: MutationView<'_, Array<i64>>,
mutator: &mut StructuralMutatorView<'_, Self>,
- ) -> Result<UnchangedOr<Array<i64>>> {
- mutator.default_mutate(self, value)?.try_cast()
+ ) -> Result<UnchangedOr<Any>> {
+ mutator.default_mutate(self, value)
}
}
let mutated = structural_mutate(Array::from_vec(vec![1i64, 2]), Typed)