1 /// Asserts that the type implements exactly one in a set of traits. 2 /// 3 /// Related: 4 /// - [`assert_impl_any!`] 5 /// - [`assert_impl_all!`] 6 /// - [`assert_impl_not_all!`] 7 /// - [`assert_impl_not_any!`] 8 /// 9 /// # Examples 10 /// 11 /// Given some type `Foo`, it is expected to implement either `Snap`, `Crackle`, 12 /// or `Pop`: 13 /// 14 /// ```compile_fail 15 /// # use static_assertions::assert_impl_one; fn main() {} 16 /// struct Foo; 17 /// 18 /// trait Snap {} 19 /// trait Crackle {} 20 /// trait Pop {} 21 /// 22 /// assert_impl_one!(Foo: Snap, Crackle, Pop); 23 /// ``` 24 /// 25 /// If _only_ `Crackle` is implemented, the assertion passes: 26 /// 27 /// ``` 28 /// # use static_assertions::assert_impl_one; fn main() {} 29 /// # struct Foo; 30 /// # trait Snap {} 31 /// # trait Crackle {} 32 /// # trait Pop {} 33 /// impl Crackle for Foo {} 34 /// 35 /// assert_impl_one!(Foo: Snap, Crackle, Pop); 36 /// ``` 37 /// 38 /// If `Snap` or `Pop` is _also_ implemented, the assertion fails: 39 /// 40 /// ```compile_fail 41 /// # use static_assertions::assert_impl_one; fn main() {} 42 /// # struct Foo; 43 /// # trait Snap {} 44 /// # trait Crackle {} 45 /// # trait Pop {} 46 /// # impl Crackle for Foo {} 47 /// impl Pop for Foo {} 48 /// 49 /// assert_impl_one!(Foo: Snap, Crackle, Pop); 50 /// ``` 51 /// 52 /// [`assert_impl_any!`]: macro.assert_impl_any.html 53 /// [`assert_impl_all!`]: macro.assert_impl_all.html 54 /// [`assert_impl_not_all!`]: macro.assert_not_impl_all.html 55 /// [`assert_impl_not_any!`]: macro.assert_not_impl_any.html 56 #[macro_export] 57 macro_rules! assert_impl_one { 58 ($x:ty: $($t:path),+ $(,)?) => { 59 const _: fn() = || { 60 // Generic trait that must be implemented for `$x` exactly once. 61 trait AmbiguousIfMoreThanOne<A> { 62 // Required for actually being able to reference the trait. 63 fn some_item() {} 64 } 65 66 // Creates multiple scoped `Token` types for each trait `$t`, over 67 // which a specialized `AmbiguousIfMoreThanOne<Token>` is 68 // implemented for every type that implements `$t`. 69 $({ 70 #[allow(dead_code)] 71 struct Token; 72 73 impl<T: ?Sized + $t> AmbiguousIfMoreThanOne<Token> for T {} 74 })+ 75 76 // If there is only one specialized trait impl, type inference with 77 // `_` can be resolved and this can compile. Fails to compile if 78 // `$x` implements more than one `AmbiguousIfMoreThanOne<Token>` or 79 // does not implement any at all. 80 let _ = <$x as AmbiguousIfMoreThanOne<_>>::some_item; 81 }; 82 }; 83 } 84 85 /// Asserts that the type implements _all_ of the given traits. 86 /// 87 /// See [`assert_impl_not_all!`] for achieving the opposite effect. 88 /// 89 /// # Examples 90 /// 91 /// This can be used to ensure types implement auto traits such as [`Send`] and 92 /// [`Sync`], as well as traits with [blanket `impl`s][blanket]. 93 /// 94 /// ``` 95 /// # #[macro_use] extern crate static_assertions; fn main() {} 96 /// assert_impl_all!(u32: Copy, Send); 97 /// assert_impl_all!(&str: Into<String>); 98 /// ``` 99 /// 100 /// The following example fails to compile because raw pointers do not implement 101 /// [`Send`] since they cannot be moved between threads safely: 102 /// 103 /// ```compile_fail 104 /// # #[macro_use] extern crate static_assertions; fn main() {} 105 /// assert_impl_all!(*const u8: Send); 106 /// ``` 107 /// 108 /// [`assert_impl_not_all!`]: macro.assert_not_impl_all.html 109 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 110 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 111 /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 112 #[macro_export(local_inner_macros)] 113 macro_rules! assert_impl_all { 114 ($ty:ty: $($traits:path),+ $(,)?) => { 115 assert_impl!($ty: $( ($traits) )&+); 116 }; 117 } 118 119 /// Asserts that the type implements _any_ of the given traits. 120 /// 121 /// See [`assert_impl_not_any!`] for achieving the opposite effect. 122 /// 123 /// # Examples 124 /// 125 /// `u8` cannot be converted from `u16`, but it can be converted into `u16`: 126 /// 127 /// ``` 128 /// # #[macro_use] extern crate static_assertions; fn main() {} 129 /// assert_impl_any!(u8: From<u16>, Into<u16>); 130 /// ``` 131 /// 132 /// The unit type cannot be converted from `u8` or `u16`, but it does implement 133 /// [`Send`]: 134 /// 135 /// ``` 136 /// # #[macro_use] extern crate static_assertions; fn main() {} 137 /// assert_impl_any!((): From<u8>, From<u16>, Send); 138 /// ``` 139 /// 140 /// The following example fails to compile because raw pointers do not implement 141 /// [`Send`] or [`Sync`] since they cannot be moved or shared between threads 142 /// safely: 143 /// 144 /// ```compile_fail 145 /// # #[macro_use] extern crate static_assertions; fn main() {} 146 /// assert_impl_any!(*const u8: Send, Sync); 147 /// ``` 148 /// 149 /// [`assert_impl_not_any!`]: macro.assert_not_impl_any.html 150 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 151 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 152 #[macro_export(local_inner_macros)] 153 macro_rules! assert_impl_any { 154 ($ty:ty: $($traits:path),+ $(,)?) => { 155 assert_impl!($ty: $( ($traits) )|+); 156 }; 157 } 158 159 /// Asserts that the type does **not** implement _all_ of the given traits. 160 /// 161 /// This can be used to ensure types do not implement auto traits such as 162 /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. 163 /// 164 /// Note that the combination of all provided traits is required to not be 165 /// implemented. If you want to check that none of multiple traits are 166 /// implemented you should invoke [`assert_impl_not_any!`] instead. 167 /// 168 /// # Examples 169 /// 170 /// Although `u32` implements `From<u16>`, it does not implement `Into<usize>`: 171 /// 172 /// ``` 173 /// # #[macro_use] extern crate static_assertions; fn main() {} 174 /// assert_impl_not_all!(u32: From<u16>, Into<usize>); 175 /// ``` 176 /// 177 /// The following example fails to compile since `u32` can be converted into 178 /// `u64`. 179 /// 180 /// ```compile_fail 181 /// # #[macro_use] extern crate static_assertions; fn main() {} 182 /// assert_impl_not_all!(u32: Into<u64>); 183 /// ``` 184 /// 185 /// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]: 186 /// 187 /// ``` 188 /// # #[macro_use] extern crate static_assertions; fn main() {} 189 /// use std::cell::Cell; 190 /// 191 /// assert_impl_not_all!(Cell<u32>: Sync, Send); 192 /// ``` 193 /// 194 /// But it is [`Send`], so this fails to compile: 195 /// 196 /// ```compile_fail 197 /// # #[macro_use] extern crate static_assertions; fn main() {} 198 /// # std::cell::Cell; 199 /// assert_impl_not_all!(Cell<u32>: Send); 200 /// ``` 201 /// 202 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 203 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 204 /// [`assert_impl_not_any!`]: macro.assert_impl_not_any.html 205 /// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html 206 /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 207 #[macro_export(local_inner_macros)] 208 macro_rules! assert_impl_not_all { 209 ($ty:ty: $($traits:path),+ $(,)?) => { 210 assert_impl!($ty: !( $( ($traits) )&+ )); 211 }; 212 } 213 214 /// Asserts that the type does **not** implement _all_ of the given traits. 215 /// 216 /// This macro has been deprecated in favor of 217 /// [`assert_impl_not_all!`](macro.assert_impl_not_all.html). 218 #[deprecated( 219 since = "1.2.0", 220 note = "Please use the 'assert_impl_not_all' macro instead" 221 )] 222 #[macro_export(local_inner_macros)] 223 macro_rules! assert_not_impl_all { 224 ($($t:tt)*) => { 225 assert_impl_not_all!($($t)*); 226 }; 227 } 228 229 /// Asserts that the type does **not** implement _any_ of the given traits. 230 /// 231 /// This can be used to ensure types do not implement auto traits such as 232 /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. 233 /// 234 /// This macro causes a compilation failure if any of the provided individual 235 /// traits are implemented for the type. If you want to check that a combination 236 /// of traits is not implemented you should invoke [`assert_impl_not_all!`] 237 /// instead. For single traits both macros behave the same. 238 /// 239 /// # Examples 240 /// 241 /// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, 242 /// the following would fail to compile: 243 /// 244 /// ``` 245 /// # #[macro_use] extern crate static_assertions; fn main() {} 246 /// assert_impl_not_any!(u32: Into<usize>, Into<u8>); 247 /// ``` 248 /// 249 /// This is also good for simple one-off cases: 250 /// 251 /// ``` 252 /// # #[macro_use] extern crate static_assertions; fn main() {} 253 /// assert_impl_not_any!(&'static mut u8: Copy); 254 /// ``` 255 /// 256 /// The following example fails to compile since `u32` can be converted into 257 /// `u64` even though it can not be converted into a `u16`: 258 /// 259 /// ```compile_fail 260 /// # #[macro_use] extern crate static_assertions; fn main() {} 261 /// assert_impl_not_any!(u32: Into<u64>, Into<u16>); 262 /// ``` 263 /// 264 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 265 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 266 /// [`assert_impl_not_all!`]: macro.assert_impl_not_all.html 267 /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 268 #[macro_export(local_inner_macros)] 269 macro_rules! assert_impl_not_any { 270 ($ty:ty: $($traits:path),+ $(,)?) => { 271 assert_impl!($ty: !( $( ($traits) )|+ )); 272 }; 273 } 274 275 /// Asserts that the type does **not** implement _any_ of the given traits. 276 /// 277 /// This macro has been deprecated in favor of 278 /// [`assert_impl_not_any!`](macro.assert_impl_not_any.html). 279 #[deprecated( 280 since = "1.2.0", 281 note = "Please use the 'assert_impl_not_any' macro instead" 282 )] 283 #[macro_export(local_inner_macros)] 284 macro_rules! assert_not_impl_any { 285 ($($t:tt)*) => { 286 assert_impl_not_any!($($t)*); 287 }; 288 } 289 290 /// Asserts that the type implements a logical trait expression. 291 /// 292 /// This macro causes a compilation failure if the expression is not satisfied. 293 /// 294 /// See [`does_impl!`](macro.does_impl.html) for simply getting a [`bool`] from 295 /// this condition without asserting it. 296 /// 297 /// # Syntax 298 /// 299 /// ```skip 300 /// assert_impl!(<type>: <trait_expr>); 301 /// assert_impl!(for(<type>: <bounds>) <type>: <trait_expr>); 302 /// ``` 303 /// 304 /// where: 305 /// 306 /// - `<type>` is a type (that must not depend on a generic parameter) 307 /// 308 /// - `<trait_expr>` is an expression made out of trait names, combined with `!` 309 /// for negation, `&` for conjunction, `|` for disjunction and parentheses for 310 /// grouping. 311 /// 312 /// - `<bounds>` is a trait bounds expression. 313 /// 314 /// For technical reasons: 315 /// 316 /// - Traits (like `Into<u8>`) that are not a single identifier must be 317 /// surrounded by parentheses. 318 /// 319 /// - The usual operator priority is not respected: `x & y | z` is parsed as 320 /// `x & (y | z)`. 321 /// 322 /// # Examples 323 /// 324 /// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, 325 /// the following would fail to compile: 326 /// 327 /// ``` 328 /// # #[macro_use] extern crate static_assertions; fn main() {} 329 /// assert_impl!(u32: !((Into<usize>) & (Into<u8>))); 330 /// ``` 331 /// 332 /// Check that a type is [`Send`] but not [`Sync`]. 333 /// 334 /// ``` 335 /// # #[macro_use] extern crate static_assertions; fn main() {} 336 /// use std::cell::Cell; 337 /// 338 /// assert_impl!(Cell<u32>: Send & !Sync); 339 /// ``` 340 /// 341 /// Check simple one-off cases: 342 /// 343 /// ``` 344 /// # #[macro_use] extern crate static_assertions; fn main() {} 345 /// assert_impl!(&'static mut u8: !Copy); 346 /// ``` 347 /// 348 /// Check that a type is _always_ [`Clone`] even when its parameter isn't: 349 /// 350 /// ``` 351 /// # #[macro_use] extern crate static_assertions; fn main() {} 352 /// use std::rc::Rc; 353 /// 354 /// assert_impl!(for(T) Rc<T>: Clone); 355 /// ``` 356 /// 357 /// The following example fails to compile since `u64` cannot be converted into 358 /// either `u32` or `u16`: 359 /// 360 /// ```compile_fail 361 /// # #[macro_use] extern crate static_assertions; fn main() {} 362 /// assert_impl!(u64: (Into<u32>) | (Into<u16>)); 363 /// ``` 364 /// 365 /// [`bool`]: https://doc.rust-lang.org/std/primitive.bool.html 366 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 367 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 368 /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html 369 #[macro_export(local_inner_macros)] 370 macro_rules! assert_impl { 371 (for($($generic:tt)*) $ty:ty: $($rest:tt)*) => { 372 const _: () = { 373 fn assert_impl<$($generic)*>() { 374 // Construct an expression using `True`/`False` and their 375 // operators, that corresponds to the provided expression. 376 let _: $crate::True = $crate::_does_impl!($ty: $($rest)*); 377 } 378 }; 379 }; 380 ($ty:ty: $($rest:tt)*) => { 381 // Construct an expression using `True`/`False` and their operators, 382 // that corresponds to the provided expression. 383 const _: $crate::True = $crate::_does_impl!($ty: $($rest)*); 384 }; 385 } 386