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