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