1 /// Asserts that the type does **not** implement _all_ of the given traits. 2 /// 3 /// This can be used to ensure types do not implement auto traits such as 4 /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. 5 /// 6 /// Note that the combination of all provided traits is required to not be 7 /// implemented. If you want to check that none of multiple traits are 8 /// implemented you should invoke [`assert_not_impl_any!`] instead. 9 /// 10 /// # Examples 11 /// 12 /// On stable Rust, using the macro requires a unique “label” when used in a 13 /// module scope: 14 /// 15 #[cfg_attr(feature = "nightly", doc = "```ignore")] 16 #[cfg_attr(not(feature = "nightly"), doc = "```")] 17 /// # #[macro_use] extern crate static_assertions; 18 /// # use static_assertions::_core::cell::Cell; 19 /// # fn main() {} 20 /// assert_not_impl_all!(ptr0; *const u16, Send, Sync); 21 /// assert_not_impl_all!(ptr1; *const u8, Send, Sync); 22 /// ``` 23 /// 24 /// The [labeling limitation](index.html#limitations) is not necessary if 25 /// compiling on nightly Rust with the `nightly` feature enabled: 26 /// 27 #[cfg_attr(feature = "nightly", doc = "```")] 28 #[cfg_attr(not(feature = "nightly"), doc = "```ignore")] 29 /// #![feature(underscore_const_names)] 30 /// # #[macro_use] extern crate static_assertions; 31 /// 32 /// assert_not_impl_all!(&'static mut u8, Copy); 33 /// 34 /// fn main() { 35 /// assert_not_impl_all!(u32, Into<usize>); 36 /// } 37 /// ``` 38 /// 39 /// The following example fails to compile since `u32` can be converted into 40 /// `u64`. 41 /// 42 /// ```compile_fail 43 /// # #[macro_use] extern crate static_assertions; 44 /// # fn main() {} 45 /// assert_not_impl_all!(u32, Into<u64>); 46 /// ``` 47 /// 48 /// `Cell<u32>` is not both `Sync` and `Send`. 49 /// 50 #[cfg_attr(feature = "nightly", doc = "```ignore")] 51 #[cfg_attr(not(feature = "nightly"), doc = "```")] 52 /// # #[macro_use] extern crate static_assertions; 53 /// # use static_assertions::_core::cell::Cell; 54 /// # fn main() {} 55 /// assert_not_impl_all!(cell; Cell<u32>, Sync, Send); 56 /// ``` 57 /// But it is `Send`, so this fails to compile. 58 /// 59 /// ```compile_fail 60 /// # #[macro_use] extern crate static_assertions; 61 /// # use static_assertions::_core::cell::Cell; 62 /// # fn main() {} 63 /// assert_not_impl_all!(cell; Cell<u32>, Send); 64 /// ``` 65 /// 66 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 67 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 68 /// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html 69 /// [blanket]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 70 #[macro_export(local_inner_macros)] 71 macro_rules! assert_not_impl_all { 72 ($($xs:tt)+) => { _assert_not_impl_all!($($xs)+); }; 73 } 74 75 /// Asserts that the type does **not** implement _any_ of the given traits. 76 /// 77 /// This can be used to ensure types do not implement auto traits such as 78 /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. 79 /// 80 /// The result of the macro fails to compile if any of the provided individual 81 /// traits are implemented for the type. If you want to check that a combination 82 /// of traits is not implemented you should invoke [`assert_not_impl_all!`] 83 /// instead. For single traits both macros behave the same. 84 /// 85 /// # Examples 86 /// 87 /// On stable Rust, using the macro requires a unique “label” when used in a 88 /// module scope: 89 /// 90 #[cfg_attr(feature = "nightly", doc = "```ignore")] 91 #[cfg_attr(not(feature = "nightly"), doc = "```")] 92 /// # #[macro_use] extern crate static_assertions; 93 /// # fn main() {} 94 /// assert_not_impl_any!(ptr0; *const u16, Send); 95 /// assert_not_impl_any!(ptr1; *const u8, Send, Sync); 96 /// ``` 97 /// 98 /// The [labeling limitation](index.html#limitations) is not necessary if 99 /// compiling on nightly Rust with the `nightly` feature enabled: 100 /// 101 #[cfg_attr(feature = "nightly", doc = "```")] 102 #[cfg_attr(not(feature = "nightly"), doc = "```ignore")] 103 /// #![feature(underscore_const_names)] 104 /// # #[macro_use] extern crate static_assertions; 105 /// 106 /// assert_not_impl_any!(&'static mut u8, Copy); 107 /// 108 /// fn main() { 109 /// assert_not_impl_any!(u32, Into<usize>); 110 /// } 111 /// ``` 112 /// 113 /// The following example fails to compile since `u32` can be converted into 114 /// `u64` even though it can not be converted into a `u16`. 115 /// 116 /// ```compile_fail 117 /// # #[macro_use] extern crate static_assertions; 118 /// # fn main() {} 119 /// assert_not_impl_any!(u32, Into<u64>, Into<u16>); 120 /// ``` 121 /// 122 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 123 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 124 /// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html 125 /// [blanket]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 126 #[macro_export(local_inner_macros)] 127 macro_rules! assert_not_impl_any { 128 ($($xs:tt)+) => { _assert_not_impl_any!($($xs)+); }; 129 } 130 131 #[doc(hidden)] 132 #[cfg(feature = "nightly")] 133 #[macro_export(local_inner_macros)] 134 macro_rules! _assert_not_impl_all { 135 ($x:ty, $($t:path),+ $(,)*) => { 136 const _: fn() -> () = || { 137 #[allow(dead_code)] 138 struct Invalid; 139 trait AmbiguousIfImpl<A> { fn some_item() {} } 140 141 impl<T: ?Sized> AmbiguousIfImpl<()> for T {} 142 impl<T: ?Sized $(+ $t)*> AmbiguousIfImpl<Invalid> for T {} 143 144 let _ = <$x as AmbiguousIfImpl<_>>::some_item; 145 }; 146 }; 147 } 148 149 #[doc(hidden)] 150 #[cfg(not(feature = "nightly"))] 151 #[macro_export(local_inner_macros)] 152 macro_rules! _assert_not_impl_all { 153 ($x:ty, $($t:path),+ $(,)*) => { 154 { 155 #[allow(dead_code)] 156 struct Invalid; 157 trait AmbiguousIfImpl<A> { fn some_item() {} } 158 159 impl<T: ?Sized> AmbiguousIfImpl<()> for T {} 160 impl<T: ?Sized $(+ $t)*> AmbiguousIfImpl<Invalid> for T {} 161 162 let _ = <$x as AmbiguousIfImpl<_>>::some_item; 163 } 164 }; 165 ($label:ident; $($xs:tt)+) => { 166 #[allow(dead_code, non_snake_case)] 167 fn $label() { assert_not_impl_all!($($xs)+); } 168 }; 169 } 170 171 #[doc(hidden)] 172 #[cfg(feature = "nightly")] 173 #[macro_export(local_inner_macros)] 174 macro_rules! _assert_not_impl_any { 175 ($x:ty, $($t:path),+ $(,)*) => { 176 const _: fn() -> () = || { 177 trait AmbiguousIfImpl<A> { fn some_item() {} } 178 179 impl<T: ?Sized> AmbiguousIfImpl<()> for T {} 180 $({ 181 #[allow(dead_code)] 182 struct Invalid; 183 impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {} 184 })+ 185 186 let _ = <$x as AmbiguousIfImpl<_>>::some_item; 187 }; 188 }; 189 } 190 191 #[doc(hidden)] 192 #[cfg(not(feature = "nightly"))] 193 #[macro_export(local_inner_macros)] 194 macro_rules! _assert_not_impl_any { 195 ($x:ty, $($t:path),+ $(,)*) => { 196 { 197 trait AmbiguousIfImpl<A> { fn some_item() {} } 198 199 impl<T: ?Sized> AmbiguousIfImpl<()> for T {} 200 $({ 201 #[allow(dead_code)] 202 struct Invalid; 203 impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {} 204 })+ 205 206 let _ = <$x as AmbiguousIfImpl<_>>::some_item; 207 } 208 }; 209 ($label:ident; $($xs:tt)+) => { 210 #[allow(dead_code, non_snake_case)] 211 fn $label() { assert_not_impl_any!($($xs)+); } 212 }; 213 } 214