1bcab3026Sopenharmony_ci/// Asserts that the type implements exactly one in a set of traits.
2bcab3026Sopenharmony_ci///
3bcab3026Sopenharmony_ci/// Related:
4bcab3026Sopenharmony_ci/// - [`assert_impl_any!`]
5bcab3026Sopenharmony_ci/// - [`assert_impl_all!`]
6bcab3026Sopenharmony_ci/// - [`assert_not_impl_all!`]
7bcab3026Sopenharmony_ci/// - [`assert_not_impl_any!`]
8bcab3026Sopenharmony_ci///
9bcab3026Sopenharmony_ci/// # Examples
10bcab3026Sopenharmony_ci///
11bcab3026Sopenharmony_ci/// Given some type `Foo`, it is expected to implement either `Snap`, `Crackle`,
12bcab3026Sopenharmony_ci/// or `Pop`:
13bcab3026Sopenharmony_ci///
14bcab3026Sopenharmony_ci/// ```compile_fail
15bcab3026Sopenharmony_ci/// # use static_assertions::assert_impl_one; fn main() {}
16bcab3026Sopenharmony_ci/// struct Foo;
17bcab3026Sopenharmony_ci///
18bcab3026Sopenharmony_ci/// trait Snap {}
19bcab3026Sopenharmony_ci/// trait Crackle {}
20bcab3026Sopenharmony_ci/// trait Pop {}
21bcab3026Sopenharmony_ci///
22bcab3026Sopenharmony_ci/// assert_impl_one!(Foo: Snap, Crackle, Pop);
23bcab3026Sopenharmony_ci/// ```
24bcab3026Sopenharmony_ci///
25bcab3026Sopenharmony_ci/// If _only_ `Crackle` is implemented, the assertion passes:
26bcab3026Sopenharmony_ci///
27bcab3026Sopenharmony_ci/// ```
28bcab3026Sopenharmony_ci/// # use static_assertions::assert_impl_one; fn main() {}
29bcab3026Sopenharmony_ci/// # struct Foo;
30bcab3026Sopenharmony_ci/// # trait Snap {}
31bcab3026Sopenharmony_ci/// # trait Crackle {}
32bcab3026Sopenharmony_ci/// # trait Pop {}
33bcab3026Sopenharmony_ci/// impl Crackle for Foo {}
34bcab3026Sopenharmony_ci///
35bcab3026Sopenharmony_ci/// assert_impl_one!(Foo: Snap, Crackle, Pop);
36bcab3026Sopenharmony_ci/// ```
37bcab3026Sopenharmony_ci///
38bcab3026Sopenharmony_ci/// If `Snap` or `Pop` is _also_ implemented, the assertion fails:
39bcab3026Sopenharmony_ci///
40bcab3026Sopenharmony_ci/// ```compile_fail
41bcab3026Sopenharmony_ci/// # use static_assertions::assert_impl_one; fn main() {}
42bcab3026Sopenharmony_ci/// # struct Foo;
43bcab3026Sopenharmony_ci/// # trait Snap {}
44bcab3026Sopenharmony_ci/// # trait Crackle {}
45bcab3026Sopenharmony_ci/// # trait Pop {}
46bcab3026Sopenharmony_ci/// # impl Crackle for Foo {}
47bcab3026Sopenharmony_ci/// impl Pop for Foo {}
48bcab3026Sopenharmony_ci///
49bcab3026Sopenharmony_ci/// assert_impl_one!(Foo: Snap, Crackle, Pop);
50bcab3026Sopenharmony_ci/// ```
51bcab3026Sopenharmony_ci///
52bcab3026Sopenharmony_ci/// [`assert_impl_any!`]:     macro.assert_impl_any.html
53bcab3026Sopenharmony_ci/// [`assert_impl_all!`]:     macro.assert_impl_all.html
54bcab3026Sopenharmony_ci/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html
55bcab3026Sopenharmony_ci/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html
56bcab3026Sopenharmony_ci#[macro_export]
57bcab3026Sopenharmony_cimacro_rules! assert_impl_one {
58bcab3026Sopenharmony_ci    ($x:ty: $($t:path),+ $(,)?) => {
59bcab3026Sopenharmony_ci        const _: fn() = || {
60bcab3026Sopenharmony_ci            // Generic trait that must be implemented for `$x` exactly once.
61bcab3026Sopenharmony_ci            trait AmbiguousIfMoreThanOne<A> {
62bcab3026Sopenharmony_ci                // Required for actually being able to reference the trait.
63bcab3026Sopenharmony_ci                fn some_item() {}
64bcab3026Sopenharmony_ci            }
65bcab3026Sopenharmony_ci
66bcab3026Sopenharmony_ci            // Creates multiple scoped `Token` types for each trait `$t`, over
67bcab3026Sopenharmony_ci            // which a specialized `AmbiguousIfMoreThanOne<Token>` is
68bcab3026Sopenharmony_ci            // implemented for every type that implements `$t`.
69bcab3026Sopenharmony_ci            $({
70bcab3026Sopenharmony_ci                #[allow(dead_code)]
71bcab3026Sopenharmony_ci                struct Token;
72bcab3026Sopenharmony_ci
73bcab3026Sopenharmony_ci                impl<T: ?Sized + $t> AmbiguousIfMoreThanOne<Token> for T {}
74bcab3026Sopenharmony_ci            })+
75bcab3026Sopenharmony_ci
76bcab3026Sopenharmony_ci            // If there is only one specialized trait impl, type inference with
77bcab3026Sopenharmony_ci            // `_` can be resolved and this can compile. Fails to compile if
78bcab3026Sopenharmony_ci            // `$x` implements more than one `AmbiguousIfMoreThanOne<Token>` or
79bcab3026Sopenharmony_ci            // does not implement any at all.
80bcab3026Sopenharmony_ci            let _ = <$x as AmbiguousIfMoreThanOne<_>>::some_item;
81bcab3026Sopenharmony_ci        };
82bcab3026Sopenharmony_ci    };
83bcab3026Sopenharmony_ci}
84bcab3026Sopenharmony_ci
85bcab3026Sopenharmony_ci/// Asserts that the type implements _all_ of the given traits.
86bcab3026Sopenharmony_ci///
87bcab3026Sopenharmony_ci/// See [`assert_not_impl_all!`] for achieving the opposite effect.
88bcab3026Sopenharmony_ci///
89bcab3026Sopenharmony_ci/// # Examples
90bcab3026Sopenharmony_ci///
91bcab3026Sopenharmony_ci/// This can be used to ensure types implement auto traits such as [`Send`] and
92bcab3026Sopenharmony_ci/// [`Sync`], as well as traits with [blanket `impl`s][blanket].
93bcab3026Sopenharmony_ci///
94bcab3026Sopenharmony_ci/// ```
95bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
96bcab3026Sopenharmony_ci/// assert_impl_all!(u32: Copy, Send);
97bcab3026Sopenharmony_ci/// assert_impl_all!(&str: Into<String>);
98bcab3026Sopenharmony_ci/// ```
99bcab3026Sopenharmony_ci///
100bcab3026Sopenharmony_ci/// The following example fails to compile because raw pointers do not implement
101bcab3026Sopenharmony_ci/// [`Send`] since they cannot be moved between threads safely:
102bcab3026Sopenharmony_ci///
103bcab3026Sopenharmony_ci/// ```compile_fail
104bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
105bcab3026Sopenharmony_ci/// assert_impl_all!(*const u8: Send);
106bcab3026Sopenharmony_ci/// ```
107bcab3026Sopenharmony_ci///
108bcab3026Sopenharmony_ci/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html
109bcab3026Sopenharmony_ci/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
110bcab3026Sopenharmony_ci/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
111bcab3026Sopenharmony_ci/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
112bcab3026Sopenharmony_ci#[macro_export]
113bcab3026Sopenharmony_cimacro_rules! assert_impl_all {
114bcab3026Sopenharmony_ci    ($type:ty: $($trait:path),+ $(,)?) => {
115bcab3026Sopenharmony_ci        const _: fn() = || {
116bcab3026Sopenharmony_ci            // Only callable when `$type` implements all traits in `$($trait)+`.
117bcab3026Sopenharmony_ci            fn assert_impl_all<T: ?Sized $(+ $trait)+>() {}
118bcab3026Sopenharmony_ci            assert_impl_all::<$type>();
119bcab3026Sopenharmony_ci        };
120bcab3026Sopenharmony_ci    };
121bcab3026Sopenharmony_ci}
122bcab3026Sopenharmony_ci
123bcab3026Sopenharmony_ci/// Asserts that the type implements _any_ of the given traits.
124bcab3026Sopenharmony_ci///
125bcab3026Sopenharmony_ci/// See [`assert_not_impl_any!`] for achieving the opposite effect.
126bcab3026Sopenharmony_ci///
127bcab3026Sopenharmony_ci/// # Examples
128bcab3026Sopenharmony_ci///
129bcab3026Sopenharmony_ci/// `u8` cannot be converted from `u16`, but it can be converted into `u16`:
130bcab3026Sopenharmony_ci///
131bcab3026Sopenharmony_ci/// ```
132bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
133bcab3026Sopenharmony_ci/// assert_impl_any!(u8: From<u16>, Into<u16>);
134bcab3026Sopenharmony_ci/// ```
135bcab3026Sopenharmony_ci///
136bcab3026Sopenharmony_ci/// The unit type cannot be converted from `u8` or `u16`, but it does implement
137bcab3026Sopenharmony_ci/// [`Send`]:
138bcab3026Sopenharmony_ci///
139bcab3026Sopenharmony_ci/// ```
140bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
141bcab3026Sopenharmony_ci/// assert_impl_any!((): From<u8>, From<u16>, Send);
142bcab3026Sopenharmony_ci/// ```
143bcab3026Sopenharmony_ci///
144bcab3026Sopenharmony_ci/// The following example fails to compile because raw pointers do not implement
145bcab3026Sopenharmony_ci/// [`Send`] or [`Sync`] since they cannot be moved or shared between threads
146bcab3026Sopenharmony_ci/// safely:
147bcab3026Sopenharmony_ci///
148bcab3026Sopenharmony_ci/// ```compile_fail
149bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
150bcab3026Sopenharmony_ci/// assert_impl_any!(*const u8: Send, Sync);
151bcab3026Sopenharmony_ci/// ```
152bcab3026Sopenharmony_ci///
153bcab3026Sopenharmony_ci/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html
154bcab3026Sopenharmony_ci/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
155bcab3026Sopenharmony_ci/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
156bcab3026Sopenharmony_ci#[macro_export]
157bcab3026Sopenharmony_cimacro_rules! assert_impl_any {
158bcab3026Sopenharmony_ci    ($x:ty: $($t:path),+ $(,)?) => {
159bcab3026Sopenharmony_ci        const _: fn() = || {
160bcab3026Sopenharmony_ci            use $crate::_core::marker::PhantomData;
161bcab3026Sopenharmony_ci            use $crate::_core::ops::Deref;
162bcab3026Sopenharmony_ci
163bcab3026Sopenharmony_ci            // Fallback to use as the first iterative assignment to `previous`.
164bcab3026Sopenharmony_ci            let previous = AssertImplAnyFallback;
165bcab3026Sopenharmony_ci            struct AssertImplAnyFallback;
166bcab3026Sopenharmony_ci
167bcab3026Sopenharmony_ci            // Ensures that blanket traits can't impersonate the method. This
168bcab3026Sopenharmony_ci            // prevents a false positive attack where---if a blanket trait is in
169bcab3026Sopenharmony_ci            // scope that has `_static_assertions_impl_any`---the macro will
170bcab3026Sopenharmony_ci            // compile when it shouldn't.
171bcab3026Sopenharmony_ci            //
172bcab3026Sopenharmony_ci            // See https://github.com/nvzqz/static-assertions-rs/issues/19 for
173bcab3026Sopenharmony_ci            // more info.
174bcab3026Sopenharmony_ci            struct ActualAssertImplAnyToken;
175bcab3026Sopenharmony_ci            trait AssertImplAnyToken {}
176bcab3026Sopenharmony_ci            impl AssertImplAnyToken for ActualAssertImplAnyToken {}
177bcab3026Sopenharmony_ci            fn assert_impl_any_token<T: AssertImplAnyToken>(_: T) {}
178bcab3026Sopenharmony_ci
179bcab3026Sopenharmony_ci            $(let previous = {
180bcab3026Sopenharmony_ci                struct Wrapper<T, N>(PhantomData<T>, N);
181bcab3026Sopenharmony_ci
182bcab3026Sopenharmony_ci                // If the method for this wrapper can't be called then the
183bcab3026Sopenharmony_ci                // compiler will insert a deref and try again. This forwards the
184bcab3026Sopenharmony_ci                // compiler's next attempt to the previous wrapper.
185bcab3026Sopenharmony_ci                impl<T, N> Deref for Wrapper<T, N> {
186bcab3026Sopenharmony_ci                    type Target = N;
187bcab3026Sopenharmony_ci
188bcab3026Sopenharmony_ci                    fn deref(&self) -> &Self::Target {
189bcab3026Sopenharmony_ci                        &self.1
190bcab3026Sopenharmony_ci                    }
191bcab3026Sopenharmony_ci                }
192bcab3026Sopenharmony_ci
193bcab3026Sopenharmony_ci                // This impl is bounded on the `$t` trait, so the method can
194bcab3026Sopenharmony_ci                // only be called if `$x` implements `$t`. This is why a new
195bcab3026Sopenharmony_ci                // `Wrapper` is defined for each `previous`.
196bcab3026Sopenharmony_ci                impl<T: $t, N> Wrapper<T, N> {
197bcab3026Sopenharmony_ci                    fn _static_assertions_impl_any(&self) -> ActualAssertImplAnyToken {
198bcab3026Sopenharmony_ci                        ActualAssertImplAnyToken
199bcab3026Sopenharmony_ci                    }
200bcab3026Sopenharmony_ci                }
201bcab3026Sopenharmony_ci
202bcab3026Sopenharmony_ci                Wrapper::<$x, _>(PhantomData, previous)
203bcab3026Sopenharmony_ci            };)+
204bcab3026Sopenharmony_ci
205bcab3026Sopenharmony_ci            // Attempt to find the method that can actually be called. The found
206bcab3026Sopenharmony_ci            // method must return a type that implements the sealed `Token`
207bcab3026Sopenharmony_ci            // trait, this ensures that blanket trait methods can't cause this
208bcab3026Sopenharmony_ci            // macro to compile.
209bcab3026Sopenharmony_ci            assert_impl_any_token(previous._static_assertions_impl_any());
210bcab3026Sopenharmony_ci        };
211bcab3026Sopenharmony_ci    };
212bcab3026Sopenharmony_ci}
213bcab3026Sopenharmony_ci
214bcab3026Sopenharmony_ci/// Asserts that the type does **not** implement _all_ of the given traits.
215bcab3026Sopenharmony_ci///
216bcab3026Sopenharmony_ci/// This can be used to ensure types do not implement auto traits such as
217bcab3026Sopenharmony_ci/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket].
218bcab3026Sopenharmony_ci///
219bcab3026Sopenharmony_ci/// Note that the combination of all provided traits is required to not be
220bcab3026Sopenharmony_ci/// implemented. If you want to check that none of multiple traits are
221bcab3026Sopenharmony_ci/// implemented you should invoke [`assert_not_impl_any!`] instead.
222bcab3026Sopenharmony_ci///
223bcab3026Sopenharmony_ci/// # Examples
224bcab3026Sopenharmony_ci///
225bcab3026Sopenharmony_ci/// Although `u32` implements `From<u16>`, it does not implement `Into<usize>`:
226bcab3026Sopenharmony_ci///
227bcab3026Sopenharmony_ci/// ```
228bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
229bcab3026Sopenharmony_ci/// assert_not_impl_all!(u32: From<u16>, Into<usize>);
230bcab3026Sopenharmony_ci/// ```
231bcab3026Sopenharmony_ci///
232bcab3026Sopenharmony_ci/// The following example fails to compile since `u32` can be converted into
233bcab3026Sopenharmony_ci/// `u64`.
234bcab3026Sopenharmony_ci///
235bcab3026Sopenharmony_ci/// ```compile_fail
236bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
237bcab3026Sopenharmony_ci/// assert_not_impl_all!(u32: Into<u64>);
238bcab3026Sopenharmony_ci/// ```
239bcab3026Sopenharmony_ci///
240bcab3026Sopenharmony_ci/// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]:
241bcab3026Sopenharmony_ci///
242bcab3026Sopenharmony_ci/// ```
243bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
244bcab3026Sopenharmony_ci/// use std::cell::Cell;
245bcab3026Sopenharmony_ci///
246bcab3026Sopenharmony_ci/// assert_not_impl_all!(Cell<u32>: Sync, Send);
247bcab3026Sopenharmony_ci/// ```
248bcab3026Sopenharmony_ci///
249bcab3026Sopenharmony_ci/// But it is [`Send`], so this fails to compile:
250bcab3026Sopenharmony_ci///
251bcab3026Sopenharmony_ci/// ```compile_fail
252bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
253bcab3026Sopenharmony_ci/// # std::cell::Cell;
254bcab3026Sopenharmony_ci/// assert_not_impl_all!(Cell<u32>: Send);
255bcab3026Sopenharmony_ci/// ```
256bcab3026Sopenharmony_ci///
257bcab3026Sopenharmony_ci/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
258bcab3026Sopenharmony_ci/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
259bcab3026Sopenharmony_ci/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html
260bcab3026Sopenharmony_ci/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
261bcab3026Sopenharmony_ci/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
262bcab3026Sopenharmony_ci#[macro_export]
263bcab3026Sopenharmony_cimacro_rules! assert_not_impl_all {
264bcab3026Sopenharmony_ci    ($x:ty: $($t:path),+ $(,)?) => {
265bcab3026Sopenharmony_ci        const _: fn() = || {
266bcab3026Sopenharmony_ci            // Generic trait with a blanket impl over `()` for all types.
267bcab3026Sopenharmony_ci            trait AmbiguousIfImpl<A> {
268bcab3026Sopenharmony_ci                // Required for actually being able to reference the trait.
269bcab3026Sopenharmony_ci                fn some_item() {}
270bcab3026Sopenharmony_ci            }
271bcab3026Sopenharmony_ci
272bcab3026Sopenharmony_ci            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
273bcab3026Sopenharmony_ci
274bcab3026Sopenharmony_ci            // Used for the specialized impl when *all* traits in
275bcab3026Sopenharmony_ci            // `$($t)+` are implemented.
276bcab3026Sopenharmony_ci            #[allow(dead_code)]
277bcab3026Sopenharmony_ci            struct Invalid;
278bcab3026Sopenharmony_ci
279bcab3026Sopenharmony_ci            impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {}
280bcab3026Sopenharmony_ci
281bcab3026Sopenharmony_ci            // If there is only one specialized trait impl, type inference with
282bcab3026Sopenharmony_ci            // `_` can be resolved and this can compile. Fails to compile if
283bcab3026Sopenharmony_ci            // `$x` implements `AmbiguousIfImpl<Invalid>`.
284bcab3026Sopenharmony_ci            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
285bcab3026Sopenharmony_ci        };
286bcab3026Sopenharmony_ci    };
287bcab3026Sopenharmony_ci}
288bcab3026Sopenharmony_ci
289bcab3026Sopenharmony_ci/// Asserts that the type does **not** implement _any_ of the given traits.
290bcab3026Sopenharmony_ci///
291bcab3026Sopenharmony_ci/// This can be used to ensure types do not implement auto traits such as
292bcab3026Sopenharmony_ci/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket].
293bcab3026Sopenharmony_ci///
294bcab3026Sopenharmony_ci/// This macro causes a compilation failure if any of the provided individual
295bcab3026Sopenharmony_ci/// traits are implemented for the type. If you want to check that a combination
296bcab3026Sopenharmony_ci/// of traits is not implemented you should invoke [`assert_not_impl_all!`]
297bcab3026Sopenharmony_ci/// instead. For single traits both macros behave the same.
298bcab3026Sopenharmony_ci///
299bcab3026Sopenharmony_ci/// # Examples
300bcab3026Sopenharmony_ci///
301bcab3026Sopenharmony_ci/// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`,
302bcab3026Sopenharmony_ci/// the following would fail to compile:
303bcab3026Sopenharmony_ci///
304bcab3026Sopenharmony_ci/// ```
305bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
306bcab3026Sopenharmony_ci/// assert_not_impl_any!(u32: Into<usize>, Into<u8>);
307bcab3026Sopenharmony_ci/// ```
308bcab3026Sopenharmony_ci///
309bcab3026Sopenharmony_ci/// This is also good for simple one-off cases:
310bcab3026Sopenharmony_ci///
311bcab3026Sopenharmony_ci/// ```
312bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
313bcab3026Sopenharmony_ci/// assert_not_impl_any!(&'static mut u8: Copy);
314bcab3026Sopenharmony_ci/// ```
315bcab3026Sopenharmony_ci///
316bcab3026Sopenharmony_ci/// The following example fails to compile since `u32` can be converted into
317bcab3026Sopenharmony_ci/// `u64` even though it can not be converted into a `u16`:
318bcab3026Sopenharmony_ci///
319bcab3026Sopenharmony_ci/// ```compile_fail
320bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {}
321bcab3026Sopenharmony_ci/// assert_not_impl_any!(u32: Into<u64>, Into<u16>);
322bcab3026Sopenharmony_ci/// ```
323bcab3026Sopenharmony_ci///
324bcab3026Sopenharmony_ci/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
325bcab3026Sopenharmony_ci/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
326bcab3026Sopenharmony_ci/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html
327bcab3026Sopenharmony_ci/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
328bcab3026Sopenharmony_ci#[macro_export]
329bcab3026Sopenharmony_cimacro_rules! assert_not_impl_any {
330bcab3026Sopenharmony_ci    ($x:ty: $($t:path),+ $(,)?) => {
331bcab3026Sopenharmony_ci        const _: fn() = || {
332bcab3026Sopenharmony_ci            // Generic trait with a blanket impl over `()` for all types.
333bcab3026Sopenharmony_ci            trait AmbiguousIfImpl<A> {
334bcab3026Sopenharmony_ci                // Required for actually being able to reference the trait.
335bcab3026Sopenharmony_ci                fn some_item() {}
336bcab3026Sopenharmony_ci            }
337bcab3026Sopenharmony_ci
338bcab3026Sopenharmony_ci            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
339bcab3026Sopenharmony_ci
340bcab3026Sopenharmony_ci            // Creates multiple scoped `Invalid` types for each trait `$t`, over
341bcab3026Sopenharmony_ci            // which a specialized `AmbiguousIfImpl<Invalid>` is implemented for
342bcab3026Sopenharmony_ci            // every type that implements `$t`.
343bcab3026Sopenharmony_ci            $({
344bcab3026Sopenharmony_ci                #[allow(dead_code)]
345bcab3026Sopenharmony_ci                struct Invalid;
346bcab3026Sopenharmony_ci
347bcab3026Sopenharmony_ci                impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {}
348bcab3026Sopenharmony_ci            })+
349bcab3026Sopenharmony_ci
350bcab3026Sopenharmony_ci            // If there is only one specialized trait impl, type inference with
351bcab3026Sopenharmony_ci            // `_` can be resolved and this can compile. Fails to compile if
352bcab3026Sopenharmony_ci            // `$x` implements any `AmbiguousIfImpl<Invalid>`.
353bcab3026Sopenharmony_ci            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
354bcab3026Sopenharmony_ci        };
355bcab3026Sopenharmony_ci    };
356bcab3026Sopenharmony_ci}
357