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