• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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