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_not_impl_all!`] 7/// - [`assert_not_impl_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_not_impl_all!`]: macro.assert_not_impl_all.html 55/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html 56#[macro_export] 57macro_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_not_impl_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_not_impl_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] 113macro_rules! assert_impl_all { 114 ($type:ty: $($trait:path),+ $(,)?) => { 115 const _: fn() = || { 116 // Only callable when `$type` implements all traits in `$($trait)+`. 117 fn assert_impl_all<T: ?Sized $(+ $trait)+>() {} 118 assert_impl_all::<$type>(); 119 }; 120 }; 121} 122 123/// Asserts that the type implements _any_ of the given traits. 124/// 125/// See [`assert_not_impl_any!`] for achieving the opposite effect. 126/// 127/// # Examples 128/// 129/// `u8` cannot be converted from `u16`, but it can be converted into `u16`: 130/// 131/// ``` 132/// # #[macro_use] extern crate static_assertions; fn main() {} 133/// assert_impl_any!(u8: From<u16>, Into<u16>); 134/// ``` 135/// 136/// The unit type cannot be converted from `u8` or `u16`, but it does implement 137/// [`Send`]: 138/// 139/// ``` 140/// # #[macro_use] extern crate static_assertions; fn main() {} 141/// assert_impl_any!((): From<u8>, From<u16>, Send); 142/// ``` 143/// 144/// The following example fails to compile because raw pointers do not implement 145/// [`Send`] or [`Sync`] since they cannot be moved or shared between threads 146/// safely: 147/// 148/// ```compile_fail 149/// # #[macro_use] extern crate static_assertions; fn main() {} 150/// assert_impl_any!(*const u8: Send, Sync); 151/// ``` 152/// 153/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html 154/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 155/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 156#[macro_export] 157macro_rules! assert_impl_any { 158 ($x:ty: $($t:path),+ $(,)?) => { 159 const _: fn() = || { 160 use $crate::_core::marker::PhantomData; 161 use $crate::_core::ops::Deref; 162 163 // Fallback to use as the first iterative assignment to `previous`. 164 let previous = AssertImplAnyFallback; 165 struct AssertImplAnyFallback; 166 167 // Ensures that blanket traits can't impersonate the method. This 168 // prevents a false positive attack where---if a blanket trait is in 169 // scope that has `_static_assertions_impl_any`---the macro will 170 // compile when it shouldn't. 171 // 172 // See https://github.com/nvzqz/static-assertions-rs/issues/19 for 173 // more info. 174 struct ActualAssertImplAnyToken; 175 trait AssertImplAnyToken {} 176 impl AssertImplAnyToken for ActualAssertImplAnyToken {} 177 fn assert_impl_any_token<T: AssertImplAnyToken>(_: T) {} 178 179 $(let previous = { 180 struct Wrapper<T, N>(PhantomData<T>, N); 181 182 // If the method for this wrapper can't be called then the 183 // compiler will insert a deref and try again. This forwards the 184 // compiler's next attempt to the previous wrapper. 185 impl<T, N> Deref for Wrapper<T, N> { 186 type Target = N; 187 188 fn deref(&self) -> &Self::Target { 189 &self.1 190 } 191 } 192 193 // This impl is bounded on the `$t` trait, so the method can 194 // only be called if `$x` implements `$t`. This is why a new 195 // `Wrapper` is defined for each `previous`. 196 impl<T: $t, N> Wrapper<T, N> { 197 fn _static_assertions_impl_any(&self) -> ActualAssertImplAnyToken { 198 ActualAssertImplAnyToken 199 } 200 } 201 202 Wrapper::<$x, _>(PhantomData, previous) 203 };)+ 204 205 // Attempt to find the method that can actually be called. The found 206 // method must return a type that implements the sealed `Token` 207 // trait, this ensures that blanket trait methods can't cause this 208 // macro to compile. 209 assert_impl_any_token(previous._static_assertions_impl_any()); 210 }; 211 }; 212} 213 214/// Asserts that the type does **not** implement _all_ of the given traits. 215/// 216/// This can be used to ensure types do not implement auto traits such as 217/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. 218/// 219/// Note that the combination of all provided traits is required to not be 220/// implemented. If you want to check that none of multiple traits are 221/// implemented you should invoke [`assert_not_impl_any!`] instead. 222/// 223/// # Examples 224/// 225/// Although `u32` implements `From<u16>`, it does not implement `Into<usize>`: 226/// 227/// ``` 228/// # #[macro_use] extern crate static_assertions; fn main() {} 229/// assert_not_impl_all!(u32: From<u16>, Into<usize>); 230/// ``` 231/// 232/// The following example fails to compile since `u32` can be converted into 233/// `u64`. 234/// 235/// ```compile_fail 236/// # #[macro_use] extern crate static_assertions; fn main() {} 237/// assert_not_impl_all!(u32: Into<u64>); 238/// ``` 239/// 240/// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]: 241/// 242/// ``` 243/// # #[macro_use] extern crate static_assertions; fn main() {} 244/// use std::cell::Cell; 245/// 246/// assert_not_impl_all!(Cell<u32>: Sync, Send); 247/// ``` 248/// 249/// But it is [`Send`], so this fails to compile: 250/// 251/// ```compile_fail 252/// # #[macro_use] extern crate static_assertions; fn main() {} 253/// # std::cell::Cell; 254/// assert_not_impl_all!(Cell<u32>: Send); 255/// ``` 256/// 257/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 258/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 259/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html 260/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html 261/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 262#[macro_export] 263macro_rules! assert_not_impl_all { 264 ($x:ty: $($t:path),+ $(,)?) => { 265 const _: fn() = || { 266 // Generic trait with a blanket impl over `()` for all types. 267 trait AmbiguousIfImpl<A> { 268 // Required for actually being able to reference the trait. 269 fn some_item() {} 270 } 271 272 impl<T: ?Sized> AmbiguousIfImpl<()> for T {} 273 274 // Used for the specialized impl when *all* traits in 275 // `$($t)+` are implemented. 276 #[allow(dead_code)] 277 struct Invalid; 278 279 impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} 280 281 // If there is only one specialized trait impl, type inference with 282 // `_` can be resolved and this can compile. Fails to compile if 283 // `$x` implements `AmbiguousIfImpl<Invalid>`. 284 let _ = <$x as AmbiguousIfImpl<_>>::some_item; 285 }; 286 }; 287} 288 289/// Asserts that the type does **not** implement _any_ of the given traits. 290/// 291/// This can be used to ensure types do not implement auto traits such as 292/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. 293/// 294/// This macro causes a compilation failure if any of the provided individual 295/// traits are implemented for the type. If you want to check that a combination 296/// of traits is not implemented you should invoke [`assert_not_impl_all!`] 297/// instead. For single traits both macros behave the same. 298/// 299/// # Examples 300/// 301/// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, 302/// the following would fail to compile: 303/// 304/// ``` 305/// # #[macro_use] extern crate static_assertions; fn main() {} 306/// assert_not_impl_any!(u32: Into<usize>, Into<u8>); 307/// ``` 308/// 309/// This is also good for simple one-off cases: 310/// 311/// ``` 312/// # #[macro_use] extern crate static_assertions; fn main() {} 313/// assert_not_impl_any!(&'static mut u8: Copy); 314/// ``` 315/// 316/// The following example fails to compile since `u32` can be converted into 317/// `u64` even though it can not be converted into a `u16`: 318/// 319/// ```compile_fail 320/// # #[macro_use] extern crate static_assertions; fn main() {} 321/// assert_not_impl_any!(u32: Into<u64>, Into<u16>); 322/// ``` 323/// 324/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html 325/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html 326/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html 327/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods 328#[macro_export] 329macro_rules! assert_not_impl_any { 330 ($x:ty: $($t:path),+ $(,)?) => { 331 const _: fn() = || { 332 // Generic trait with a blanket impl over `()` for all types. 333 trait AmbiguousIfImpl<A> { 334 // Required for actually being able to reference the trait. 335 fn some_item() {} 336 } 337 338 impl<T: ?Sized> AmbiguousIfImpl<()> for T {} 339 340 // Creates multiple scoped `Invalid` types for each trait `$t`, over 341 // which a specialized `AmbiguousIfImpl<Invalid>` is implemented for 342 // every type that implements `$t`. 343 $({ 344 #[allow(dead_code)] 345 struct Invalid; 346 347 impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {} 348 })+ 349 350 // If there is only one specialized trait impl, type inference with 351 // `_` can be resolved and this can compile. Fails to compile if 352 // `$x` implements any `AmbiguousIfImpl<Invalid>`. 353 let _ = <$x as AmbiguousIfImpl<_>>::some_item; 354 }; 355 }; 356} 357