macro_rules! define_impls_trait_ignore_lt_fn {
( #[auto_doc] $( #[$meta:meta] )* $vis:vis $fn_name:ident: $( $bounds:tt )+ ) => { ... };
(
$( #[$meta1:meta] )* #[+reliability_doc] $( #[$meta2:meta] )*
$vis:vis $fn_name:ident: $( $bounds:tt )+
) => { ... };
( $( #[$meta:meta] )* $vis:vis $fn_name:ident: $( $bounds:tt )+ ) => { ... };
}alloc and unreliable only.Expand description
Generates a function which returns true if the given type implements
specified trait. Note that all the lifetimes are erased and not accounted
for.
Library tests ensure that the impls_trait checks are performed at compile
time and are fully optimized with no runtime cost at opt-level >= 1. Note
that the release profile uses opt-level = 3 by default.
Custom attributes:
#[auto_doc]attribute enables automatic documentation generation for the generated function including theReliabilitydocumentation section.#[+reliability_doc]attribute enables automatic generation ofReliabilitydocumentation section for the generated function.
§Reliability
While it is unlikely, there is still a possibility that the functions generated by this macro may return false negatives in future Rust versions.
The correctness of the results returned by the functions depends on the following:
- Documented behavior that if
TimplementsEq, twoRcs that point to the same allocation are always equal: https://doc.rust-lang.org/1.82.0/std/rc/struct.Rc.html#method.eq. - Undocumented behavior that the
Rc::partial_eqimplementation forT: Eqwill not usePartialEq::eqif bothRcs point to the same memory location. - The assumption that the undocumented short-circuit behavior described above will be retained for optimization purposes.
There is no formal guarantee that the undocumented behavior described above
will be retained. If the implementation changes in a future Rust version,
the function may return a false negative, that is, it may return false,
even though T implements the trait. However, the implementation guarantees
that a false positive result is impossible, i.e., the function will never
return true if T does not implement the trait in any future Rust version.
Details:
- https://internals.rust-lang.org/t/rc-uses-visibly-behavior-changing-specialization-is-that-okay/16173/6,
- https://users.rust-lang.org/t/hack-to-specialize-w-write-for-vec-u8/100366,
- https://doc.rust-lang.org/1.82.0/std/rc/struct.Rc.html#method.eq,
- https://github.com/rust-lang/rust/issues/42655.
§Examples
use try_specialize::define_impls_trait_ignore_lt_fn;
define_impls_trait_ignore_lt_fn!(
#[auto_doc] pub impls_into_iterator_u32: IntoIterator<Item = u32>
);
assert!(impls_into_iterator_u32::<[u32; 4]>());
assert!(impls_into_iterator_u32::<Vec<u32>>());
assert!(!impls_into_iterator_u32::<Vec<i32>>());use try_specialize::define_impls_trait_ignore_lt_fn;
define_impls_trait_ignore_lt_fn!(
pub impls_copy_eq_ord: Copy + Eq + Ord
);
assert!(impls_copy_eq_ord::<u32>());
assert!(impls_copy_eq_ord::<[u32; 4]>());
assert!(!impls_copy_eq_ord::<Vec<u32>>());use try_specialize::define_impls_trait_ignore_lt_fn;
pub trait IsRef {}
impl<T> IsRef for &T where T: ?Sized {}
pub trait IsMutRef {}
impl<T> IsMutRef for &mut T where T: ?Sized {}
pub trait IsBox {}
impl<T> IsBox for Box<T> where T: ?Sized {}
define_impls_trait_ignore_lt_fn!(
#[+reliability_doc]
/// Returns `true` if the given type is a const reference like `&T`.
pub is_ref: IsRef
);
define_impls_trait_ignore_lt_fn!(
#[+reliability_doc]
/// Returns `true` if the given type is a mutable reference like
/// `&mut T`.
pub is_mut_ref: IsMutRef
);
define_impls_trait_ignore_lt_fn!(
#[+reliability_doc]
/// Returns `true` if the given type is a `Box<T>`-type.
pub is_box: IsBox
);
assert!(!is_ref::<u32>());
assert!(!is_ref::<[u32; 4]>());
assert!(!is_ref::<Vec<u32>>());
assert!(is_ref::<&u32>());
assert!(is_ref::<&[u32]>());
assert!(!is_ref::<&mut u32>());
assert!(!is_mut_ref::<u32>());
assert!(!is_mut_ref::<&u32>());
assert!(is_mut_ref::<&mut u32>());
assert!(!is_box::<u32>());
assert!(!is_box::<&u32>());
assert!(!is_box::<&mut u32>());
assert!(is_box::<Box<u32>>());
assert!(is_box::<Box<(char, u32, i128)>>());