define_impls_trait_ignore_lt_fn

Macro define_impls_trait_ignore_lt_fn 

Source
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 )+ ) => { ... };
}
Available on crate features 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 the Reliability documentation section.
  • #[+reliability_doc] attribute enables automatic generation of Reliability documentation 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 T implements Eq, two Rcs 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_eq implementation for T: Eq will not use PartialEq::eq if both Rcs 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:

§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)>>());