/// Asserts that the type implements exactly one in a set of traits. /// /// Related: /// - [`assert_impl_any!`] /// - [`assert_impl_all!`] /// - [`assert_impl_not_all!`] /// - [`assert_impl_not_any!`] /// /// # Examples /// /// Given some type `Foo`, it is expected to implement either `Snap`, `Crackle`, /// or `Pop`: /// /// ```compile_fail /// # use static_assertions::assert_impl_one; fn main() {} /// struct Foo; /// /// trait Snap {} /// trait Crackle {} /// trait Pop {} /// /// assert_impl_one!(Foo: Snap, Crackle, Pop); /// ``` /// /// If _only_ `Crackle` is implemented, the assertion passes: /// /// ``` /// # use static_assertions::assert_impl_one; fn main() {} /// # struct Foo; /// # trait Snap {} /// # trait Crackle {} /// # trait Pop {} /// impl Crackle for Foo {} /// /// assert_impl_one!(Foo: Snap, Crackle, Pop); /// ``` /// /// If `Snap` or `Pop` is _also_ implemented, the assertion fails: /// /// ```compile_fail /// # use static_assertions::assert_impl_one; fn main() {} /// # struct Foo; /// # trait Snap {} /// # trait Crackle {} /// # trait Pop {} /// # impl Crackle for Foo {} /// impl Pop for Foo {} /// /// assert_impl_one!(Foo: Snap, Crackle, Pop); /// ``` /// /// [`assert_impl_any!`]: macro.assert_impl_any.html /// [`assert_impl_all!`]: macro.assert_impl_all.html /// [`assert_impl_not_all!`]: macro.assert_not_impl_all.html /// [`assert_impl_not_any!`]: macro.assert_not_impl_any.html #[macro_export] macro_rules! assert_impl_one { ($x:ty: $($t:path),+ $(,)?) => { const _: fn() = || { // Generic trait that must be implemented for `$x` exactly once. trait AmbiguousIfMoreThanOne { // Required for actually being able to reference the trait. fn some_item() {} } // Creates multiple scoped `Token` types for each trait `$t`, over // which a specialized `AmbiguousIfMoreThanOne` is // implemented for every type that implements `$t`. $({ #[allow(dead_code)] struct Token; impl AmbiguousIfMoreThanOne for T {} })+ // If there is only one specialized trait impl, type inference with // `_` can be resolved and this can compile. Fails to compile if // `$x` implements more than one `AmbiguousIfMoreThanOne` or // does not implement any at all. let _ = <$x as AmbiguousIfMoreThanOne<_>>::some_item; }; }; } /// Asserts that the type implements _all_ of the given traits. /// /// See [`assert_impl_not_all!`] for achieving the opposite effect. /// /// # Examples /// /// This can be used to ensure types implement auto traits such as [`Send`] and /// [`Sync`], as well as traits with [blanket `impl`s][blanket]. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_all!(u32: Copy, Send); /// assert_impl_all!(&str: Into); /// ``` /// /// The following example fails to compile because raw pointers do not implement /// [`Send`] since they cannot be moved between threads safely: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_all!(*const u8: Send); /// ``` /// /// [`assert_impl_not_all!`]: macro.assert_not_impl_all.html /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods #[macro_export(local_inner_macros)] macro_rules! assert_impl_all { ($ty:ty: $($traits:path),+ $(,)?) => { assert_impl!($ty: $( ($traits) )&+); }; } /// Asserts that the type implements _any_ of the given traits. /// /// See [`assert_impl_not_any!`] for achieving the opposite effect. /// /// # Examples /// /// `u8` cannot be converted from `u16`, but it can be converted into `u16`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_any!(u8: From, Into); /// ``` /// /// The unit type cannot be converted from `u8` or `u16`, but it does implement /// [`Send`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_any!((): From, From, Send); /// ``` /// /// The following example fails to compile because raw pointers do not implement /// [`Send`] or [`Sync`] since they cannot be moved or shared between threads /// safely: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_any!(*const u8: Send, Sync); /// ``` /// /// [`assert_impl_not_any!`]: macro.assert_not_impl_any.html /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html #[macro_export(local_inner_macros)] macro_rules! assert_impl_any { ($ty:ty: $($traits:path),+ $(,)?) => { assert_impl!($ty: $( ($traits) )|+); }; } /// Asserts that the type does **not** implement _all_ of the given traits. /// /// This can be used to ensure types do not implement auto traits such as /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. /// /// Note that the combination of all provided traits is required to not be /// implemented. If you want to check that none of multiple traits are /// implemented you should invoke [`assert_impl_not_any!`] instead. /// /// # Examples /// /// Although `u32` implements `From`, it does not implement `Into`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_not_all!(u32: From, Into); /// ``` /// /// The following example fails to compile since `u32` can be converted into /// `u64`. /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_not_all!(u32: Into); /// ``` /// /// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::cell::Cell; /// /// assert_impl_not_all!(Cell: Sync, Send); /// ``` /// /// But it is [`Send`], so this fails to compile: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// # std::cell::Cell; /// assert_impl_not_all!(Cell: Send); /// ``` /// /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [`assert_impl_not_any!`]: macro.assert_impl_not_any.html /// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods #[macro_export(local_inner_macros)] macro_rules! assert_impl_not_all { ($ty:ty: $($traits:path),+ $(,)?) => { assert_impl!($ty: !( $( ($traits) )&+ )); }; } /// Asserts that the type does **not** implement _all_ of the given traits. /// /// This macro has been deprecated in favor of /// [`assert_impl_not_all!`](macro.assert_impl_not_all.html). #[deprecated( since = "1.2.0", note = "Please use the 'assert_impl_not_all' macro instead" )] #[macro_export(local_inner_macros)] macro_rules! assert_not_impl_all { ($($t:tt)*) => { assert_impl_not_all!($($t)*); }; } /// Asserts that the type does **not** implement _any_ of the given traits. /// /// This can be used to ensure types do not implement auto traits such as /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. /// /// This macro causes a compilation failure if any of the provided individual /// traits are implemented for the type. If you want to check that a combination /// of traits is not implemented you should invoke [`assert_impl_not_all!`] /// instead. For single traits both macros behave the same. /// /// # Examples /// /// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, /// the following would fail to compile: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_not_any!(u32: Into, Into); /// ``` /// /// This is also good for simple one-off cases: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_not_any!(&'static mut u8: Copy); /// ``` /// /// The following example fails to compile since `u32` can be converted into /// `u64` even though it can not be converted into a `u16`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_not_any!(u32: Into, Into); /// ``` /// /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [`assert_impl_not_all!`]: macro.assert_impl_not_all.html /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods #[macro_export(local_inner_macros)] macro_rules! assert_impl_not_any { ($ty:ty: $($traits:path),+ $(,)?) => { assert_impl!($ty: !( $( ($traits) )|+ )); }; } /// Asserts that the type does **not** implement _any_ of the given traits. /// /// This macro has been deprecated in favor of /// [`assert_impl_not_any!`](macro.assert_impl_not_any.html). #[deprecated( since = "1.2.0", note = "Please use the 'assert_impl_not_any' macro instead" )] #[macro_export(local_inner_macros)] macro_rules! assert_not_impl_any { ($($t:tt)*) => { assert_impl_not_any!($($t)*); }; } /// Asserts that the type implements a logical trait expression. /// /// This macro causes a compilation failure if the expression is not satisfied. /// /// See [`does_impl!`](macro.does_impl.html) for simply getting a [`bool`] from /// this condition without asserting it. /// /// # Syntax /// /// ```skip /// assert_impl!(: ); /// assert_impl!(for(: ) : ); /// ``` /// /// where: /// /// - `` is a type (that must not depend on a generic parameter) /// /// - `` is an expression made out of trait names, combined with `!` /// for negation, `&` for conjunction, `|` for disjunction and parentheses for /// grouping. /// /// - `` is a trait bounds expression. /// /// For technical reasons: /// /// - Traits (like `Into`) that are not a single identifier must be /// surrounded by parentheses. /// /// - The usual operator priority is not respected: `x & y | z` is parsed as /// `x & (y | z)`. /// /// # Examples /// /// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, /// the following would fail to compile: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl!(u32: !((Into) & (Into))); /// ``` /// /// Check that a type is [`Send`] but not [`Sync`]. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::cell::Cell; /// /// assert_impl!(Cell: Send & !Sync); /// ``` /// /// Check simple one-off cases: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl!(&'static mut u8: !Copy); /// ``` /// /// Check that a type is _always_ [`Clone`] even when its parameter isn't: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::rc::Rc; /// /// assert_impl!(for(T) Rc: Clone); /// ``` /// /// The following example fails to compile since `u64` cannot be converted into /// either `u32` or `u16`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl!(u64: (Into) | (Into)); /// ``` /// /// [`bool`]: https://doc.rust-lang.org/std/primitive.bool.html /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html #[macro_export(local_inner_macros)] macro_rules! assert_impl { (for($($generic:tt)*) $ty:ty: $($rest:tt)*) => { const _: () = { fn assert_impl<$($generic)*>() { // Construct an expression using `True`/`False` and their // operators, that corresponds to the provided expression. let _: $crate::True = $crate::_does_impl!($ty: $($rest)*); } }; }; ($ty:ty: $($rest:tt)*) => { // Construct an expression using `True`/`False` and their operators, // that corresponds to the provided expression. const _: $crate::True = $crate::_does_impl!($ty: $($rest)*); }; }