diff options
Diffstat (limited to 'third_party/rust/static_assertions/src')
-rw-r--r-- | third_party/rust/static_assertions/src/assert_cfg.rs | 49 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_eq_align.rs | 45 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_eq_size.rs | 123 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_fields.rs | 72 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_impl.rs | 356 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_obj_safe.rs | 76 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_trait.rs | 105 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/assert_type.rs | 101 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/const_assert.rs | 109 | ||||
-rw-r--r-- | third_party/rust/static_assertions/src/lib.rs | 97 |
10 files changed, 1133 insertions, 0 deletions
diff --git a/third_party/rust/static_assertions/src/assert_cfg.rs b/third_party/rust/static_assertions/src/assert_cfg.rs new file mode 100644 index 0000000000..24282c1f32 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_cfg.rs @@ -0,0 +1,49 @@ +/// Asserts that a given configuration is set. +/// +/// # Examples +/// +/// A project will simply fail to compile if the given configuration is not set. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// // We're not masochists +/// # #[cfg(not(target_pointer_width = "16"))] // Just in case +/// assert_cfg!(not(target_pointer_width = "16")); +/// ``` +/// +/// If a project does not support a set of configurations, you may want to +/// report why. There is the option of providing a compile error message string: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # #[cfg(any(unix, windows))] +/// assert_cfg!(any(unix, windows), "There is only support for Unix or Windows"); +/// +/// // User needs to specify a database back-end +/// # #[cfg(target_pointer_width = "0")] // Impossible +/// assert_cfg!(all(not(all(feature = "mysql", feature = "mongodb")), +/// any( feature = "mysql", feature = "mongodb")), +/// "Must exclusively use MySQL or MongoDB as database back-end"); +/// ``` +/// +/// Some configurations are impossible. For example, we can't be compiling for +/// both macOS _and_ Windows simultaneously: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_cfg!(all(target_os = "macos", +/// target_os = "windows"), +/// "No, that's not how it works! ಠ_ಠ"); +/// ``` +#[macro_export] +macro_rules! assert_cfg { + () => {}; + ($($cfg:meta)+, $msg:expr $(,)?) => { + #[cfg(not($($cfg)+))] + compile_error!($msg); + }; + ($($cfg:tt)*) => { + #[cfg(not($($cfg)*))] + compile_error!(concat!("Cfg does not pass: ", stringify!($($cfg)*))); + }; +} diff --git a/third_party/rust/static_assertions/src/assert_eq_align.rs b/third_party/rust/static_assertions/src/assert_eq_align.rs new file mode 100644 index 0000000000..69412daefb --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_eq_align.rs @@ -0,0 +1,45 @@ +/// Asserts that types are equal in alignment. +/// +/// This is useful when ensuring that pointer arithmetic is done correctly, or +/// when [FFI] requires a type to have the same alignment as some foreign type. +/// +/// # Examples +/// +/// A `usize` has the same alignment as any pointer type: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_align!(usize, *const u8, *mut u8); +/// ``` +/// +/// The following passes because `[i32; 4]` has the same alignment as `i32`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_align!([i32; 4], i32); +/// ``` +/// +/// The following example fails to compile because `i32x4` explicitly has 4 +/// times the alignment as `[i32; 4]`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # #[allow(non_camel_case_types)] +/// #[repr(align(16))] +/// struct i32x4([i32; 4]); +/// +/// assert_eq_align!(i32x4, [i32; 4]); +/// ``` +/// +/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface +#[macro_export] +macro_rules! assert_eq_align { + ($x:ty, $($xs:ty),+ $(,)?) => { + const _: fn() = || { + // Assigned instance must match the annotated type or else it will + // fail to compile + use $crate::_core::mem::align_of; + $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ + }; + }; +} diff --git a/third_party/rust/static_assertions/src/assert_eq_size.rs b/third_party/rust/static_assertions/src/assert_eq_size.rs new file mode 100644 index 0000000000..9c3c4901c7 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_eq_size.rs @@ -0,0 +1,123 @@ +/// Asserts that types are equal in size. +/// +/// When performing operations such as pointer casts or dealing with [`usize`] +/// versus [`u64`] versus [`u32`], the size of your types matter. That is where +/// this macro comes into play. +/// +/// # Alternatives +/// +/// There also exists [`assert_eq_size_val`](macro.assert_eq_size_val.html) and +/// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying +/// types to compare, values' sizes can be directly compared against each other. +/// +/// # Examples +/// +/// These three types, despite being very different, all have the same size: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_size!([u8; 4], (u16, u16), u32); +/// ``` +/// +/// The following example fails to compile because `u32` has 4 times the size of +/// `u8`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_size!(u32, u8); +/// ``` +/// +/// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html +/// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html +/// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html +#[macro_export] +macro_rules! assert_eq_size { + ($x:ty, $($xs:ty),+ $(,)?) => { + const _: fn() = || { + $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+ + }; + }; +} + +/// Asserts that values pointed to are equal in size. +/// +/// # Examples +/// +/// This especially is useful for when coercing pointers between different types +/// and ensuring the underlying values are the same size. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// fn operation(x: &(u32, u32), y: &[u16; 4]) { +/// assert_eq_size_ptr!(x, y); +/// // ... +/// } +/// ``` +/// +/// The following example fails to compile because byte arrays of different +/// lengths have different sizes: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// static BYTES: &[u8; 4] = &[ +/// /* ... */ +/// # 0; 4 +/// ]; +/// +/// static TABLE: &[u8; 16] = &[ +/// /* ... */ +/// # 0; 16 +/// ]; +/// +/// assert_eq_size_ptr!(BYTES, TABLE); +/// ``` +#[macro_export] +macro_rules! assert_eq_size_ptr { + ($x:expr, $($xs:expr),+ $(,)?) => { + #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)] + let _ = || unsafe { + use $crate::_core::{mem, ptr}; + let mut copy = ptr::read($x); + $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+ + mem::forget(copy); + }; + } +} + +/// Asserts that values are equal in size. +/// +/// This macro doesn't consume its arguments and thus works for +/// non-[`Clone`]able values. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// struct Byte(u8); +/// +/// let x = 10u8; +/// let y = Byte(42); // Works for non-cloneable types +/// +/// assert_eq_size_val!(x, y); +/// assert_eq_size_val!(x, y, 0u8); +/// # } +/// ``` +/// +/// Even though both values are 0, they are of types with different sizes: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// assert_eq_size_val!(0u8, 0u32); +/// # } +/// ``` +/// +/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +#[macro_export(local_inner_macros)] +macro_rules! assert_eq_size_val { + ($x:expr, $($xs:expr),+ $(,)?) => { + assert_eq_size_ptr!(&$x, $(&$xs),+); + } +} diff --git a/third_party/rust/static_assertions/src/assert_fields.rs b/third_party/rust/static_assertions/src/assert_fields.rs new file mode 100644 index 0000000000..00f6242775 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_fields.rs @@ -0,0 +1,72 @@ +/// Asserts that the type has the given fields. +/// +/// # Examples +/// +/// One common use case is when types have fields defined multiple times as a +/// result of `#[cfg]`. This can be an issue when exposing a public API. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// pub struct Ty { +/// #[cfg(windows)] +/// pub val1: u8, +/// #[cfg(not(windows))] +/// pub val1: usize, +/// +/// #[cfg(unix)] +/// pub val2: u32, +/// #[cfg(not(unix))] +/// pub val2: usize, +/// } +/// +/// // Always have `val2` regardless of OS +/// assert_fields!(Ty: val2); +/// ``` +/// +/// This macro even works with `enum` variants: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// enum Data { +/// Val { +/// id: i32, +/// name: String, +/// bytes: [u8; 128], +/// }, +/// Ptr(*const u8), +/// } +/// +/// assert_fields!(Data::Val: id, bytes); +/// ``` +/// +/// The following example fails to compile because [`Range`] does not have a field named `middle`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::ops::Range; +/// +/// assert_fields!(Range<u32>: middle); +/// ``` +/// +/// [`Range`]: https://doc.rust-lang.org/std/ops/struct.Range.html +#[macro_export] +macro_rules! assert_fields { + ($t:ident::$v:ident: $($f:ident),+) => { + #[allow(unknown_lints, unneeded_field_pattern)] + const _: fn() = || { + #[allow(dead_code, unreachable_patterns)] + fn assert(value: $t) { + match value { + $($t::$v { $f: _, .. } => {},)+ + _ => {} + } + } + }; + }; + ($t:path: $($f:ident),+) => { + #[allow(unknown_lints, unneeded_field_pattern)] + const _: fn() = || { + $(let $t { $f: _, .. };)+ + }; + }; +} diff --git a/third_party/rust/static_assertions/src/assert_impl.rs b/third_party/rust/static_assertions/src/assert_impl.rs new file mode 100644 index 0000000000..480b6b6c61 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_impl.rs @@ -0,0 +1,356 @@ +/// Asserts that the type implements exactly one in a set of traits. +/// +/// Related: +/// - [`assert_impl_any!`] +/// - [`assert_impl_all!`] +/// - [`assert_not_impl_all!`] +/// - [`assert_not_impl_any!`] +/// +/// # Examples +/// +/// Given some type `Foo`, it is expected to implement either `Snap`, `Crackle`, +/// or `Pop`: +/// +/// ```compile_fail +/// # use static_assertions::assert_impl_one; fn main() {} +/// struct Foo; +/// +/// trait Snap {} +/// trait Crackle {} +/// trait Pop {} +/// +/// assert_impl_one!(Foo: Snap, Crackle, Pop); +/// ``` +/// +/// If _only_ `Crackle` is implemented, the assertion passes: +/// +/// ``` +/// # use static_assertions::assert_impl_one; fn main() {} +/// # struct Foo; +/// # trait Snap {} +/// # trait Crackle {} +/// # trait Pop {} +/// impl Crackle for Foo {} +/// +/// assert_impl_one!(Foo: Snap, Crackle, Pop); +/// ``` +/// +/// If `Snap` or `Pop` is _also_ implemented, the assertion fails: +/// +/// ```compile_fail +/// # use static_assertions::assert_impl_one; fn main() {} +/// # struct Foo; +/// # trait Snap {} +/// # trait Crackle {} +/// # trait Pop {} +/// # impl Crackle for Foo {} +/// impl Pop for Foo {} +/// +/// assert_impl_one!(Foo: Snap, Crackle, Pop); +/// ``` +/// +/// [`assert_impl_any!`]: macro.assert_impl_any.html +/// [`assert_impl_all!`]: macro.assert_impl_all.html +/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html +/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html +#[macro_export] +macro_rules! assert_impl_one { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + // Generic trait that must be implemented for `$x` exactly once. + trait AmbiguousIfMoreThanOne<A> { + // Required for actually being able to reference the trait. + fn some_item() {} + } + + // Creates multiple scoped `Token` types for each trait `$t`, over + // which a specialized `AmbiguousIfMoreThanOne<Token>` is + // implemented for every type that implements `$t`. + $({ + #[allow(dead_code)] + struct Token; + + impl<T: ?Sized + $t> AmbiguousIfMoreThanOne<Token> for T {} + })+ + + // If there is only one specialized trait impl, type inference with + // `_` can be resolved and this can compile. Fails to compile if + // `$x` implements more than one `AmbiguousIfMoreThanOne<Token>` or + // does not implement any at all. + let _ = <$x as AmbiguousIfMoreThanOne<_>>::some_item; + }; + }; +} + +/// Asserts that the type implements _all_ of the given traits. +/// +/// See [`assert_not_impl_all!`] for achieving the opposite effect. +/// +/// # Examples +/// +/// This can be used to ensure types implement auto traits such as [`Send`] and +/// [`Sync`], as well as traits with [blanket `impl`s][blanket]. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_all!(u32: Copy, Send); +/// assert_impl_all!(&str: Into<String>); +/// ``` +/// +/// The following example fails to compile because raw pointers do not implement +/// [`Send`] since they cannot be moved between threads safely: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_all!(*const u8: Send); +/// ``` +/// +/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods +#[macro_export] +macro_rules! assert_impl_all { + ($type:ty: $($trait:path),+ $(,)?) => { + const _: fn() = || { + // Only callable when `$type` implements all traits in `$($trait)+`. + fn assert_impl_all<T: ?Sized $(+ $trait)+>() {} + assert_impl_all::<$type>(); + }; + }; +} + +/// Asserts that the type implements _any_ of the given traits. +/// +/// See [`assert_not_impl_any!`] for achieving the opposite effect. +/// +/// # Examples +/// +/// `u8` cannot be converted from `u16`, but it can be converted into `u16`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_any!(u8: From<u16>, Into<u16>); +/// ``` +/// +/// The unit type cannot be converted from `u8` or `u16`, but it does implement +/// [`Send`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_any!((): From<u8>, From<u16>, Send); +/// ``` +/// +/// The following example fails to compile because raw pointers do not implement +/// [`Send`] or [`Sync`] since they cannot be moved or shared between threads +/// safely: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_any!(*const u8: Send, Sync); +/// ``` +/// +/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +#[macro_export] +macro_rules! assert_impl_any { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + use $crate::_core::marker::PhantomData; + use $crate::_core::ops::Deref; + + // Fallback to use as the first iterative assignment to `previous`. + let previous = AssertImplAnyFallback; + struct AssertImplAnyFallback; + + // Ensures that blanket traits can't impersonate the method. This + // prevents a false positive attack where---if a blanket trait is in + // scope that has `_static_assertions_impl_any`---the macro will + // compile when it shouldn't. + // + // See https://github.com/nvzqz/static-assertions-rs/issues/19 for + // more info. + struct ActualAssertImplAnyToken; + trait AssertImplAnyToken {} + impl AssertImplAnyToken for ActualAssertImplAnyToken {} + fn assert_impl_any_token<T: AssertImplAnyToken>(_: T) {} + + $(let previous = { + struct Wrapper<T, N>(PhantomData<T>, N); + + // If the method for this wrapper can't be called then the + // compiler will insert a deref and try again. This forwards the + // compiler's next attempt to the previous wrapper. + impl<T, N> Deref for Wrapper<T, N> { + type Target = N; + + fn deref(&self) -> &Self::Target { + &self.1 + } + } + + // This impl is bounded on the `$t` trait, so the method can + // only be called if `$x` implements `$t`. This is why a new + // `Wrapper` is defined for each `previous`. + impl<T: $t, N> Wrapper<T, N> { + fn _static_assertions_impl_any(&self) -> ActualAssertImplAnyToken { + ActualAssertImplAnyToken + } + } + + Wrapper::<$x, _>(PhantomData, previous) + };)+ + + // Attempt to find the method that can actually be called. The found + // method must return a type that implements the sealed `Token` + // trait, this ensures that blanket trait methods can't cause this + // macro to compile. + assert_impl_any_token(previous._static_assertions_impl_any()); + }; + }; +} + +/// Asserts that the type does **not** implement _all_ of the given traits. +/// +/// This can be used to ensure types do not implement auto traits such as +/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. +/// +/// Note that the combination of all provided traits is required to not be +/// implemented. If you want to check that none of multiple traits are +/// implemented you should invoke [`assert_not_impl_any!`] instead. +/// +/// # Examples +/// +/// Although `u32` implements `From<u16>`, it does not implement `Into<usize>`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_all!(u32: From<u16>, Into<usize>); +/// ``` +/// +/// The following example fails to compile since `u32` can be converted into +/// `u64`. +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_all!(u32: Into<u64>); +/// ``` +/// +/// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::cell::Cell; +/// +/// assert_not_impl_all!(Cell<u32>: Sync, Send); +/// ``` +/// +/// But it is [`Send`], so this fails to compile: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # std::cell::Cell; +/// assert_not_impl_all!(Cell<u32>: Send); +/// ``` +/// +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html +/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html +/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods +#[macro_export] +macro_rules! assert_not_impl_all { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + // Generic trait with a blanket impl over `()` for all types. + trait AmbiguousIfImpl<A> { + // Required for actually being able to reference the trait. + fn some_item() {} + } + + impl<T: ?Sized> AmbiguousIfImpl<()> for T {} + + // Used for the specialized impl when *all* traits in + // `$($t)+` are implemented. + #[allow(dead_code)] + struct Invalid; + + impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} + + // If there is only one specialized trait impl, type inference with + // `_` can be resolved and this can compile. Fails to compile if + // `$x` implements `AmbiguousIfImpl<Invalid>`. + let _ = <$x as AmbiguousIfImpl<_>>::some_item; + }; + }; +} + +/// Asserts that the type does **not** implement _any_ of the given traits. +/// +/// This can be used to ensure types do not implement auto traits such as +/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. +/// +/// This macro causes a compilation failure if any of the provided individual +/// traits are implemented for the type. If you want to check that a combination +/// of traits is not implemented you should invoke [`assert_not_impl_all!`] +/// instead. For single traits both macros behave the same. +/// +/// # Examples +/// +/// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, +/// the following would fail to compile: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_any!(u32: Into<usize>, Into<u8>); +/// ``` +/// +/// This is also good for simple one-off cases: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_any!(&'static mut u8: Copy); +/// ``` +/// +/// The following example fails to compile since `u32` can be converted into +/// `u64` even though it can not be converted into a `u16`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_any!(u32: Into<u64>, Into<u16>); +/// ``` +/// +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html +/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods +#[macro_export] +macro_rules! assert_not_impl_any { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + // Generic trait with a blanket impl over `()` for all types. + trait AmbiguousIfImpl<A> { + // Required for actually being able to reference the trait. + fn some_item() {} + } + + impl<T: ?Sized> AmbiguousIfImpl<()> for T {} + + // Creates multiple scoped `Invalid` types for each trait `$t`, over + // which a specialized `AmbiguousIfImpl<Invalid>` is implemented for + // every type that implements `$t`. + $({ + #[allow(dead_code)] + struct Invalid; + + impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {} + })+ + + // If there is only one specialized trait impl, type inference with + // `_` can be resolved and this can compile. Fails to compile if + // `$x` implements any `AmbiguousIfImpl<Invalid>`. + let _ = <$x as AmbiguousIfImpl<_>>::some_item; + }; + }; +} diff --git a/third_party/rust/static_assertions/src/assert_obj_safe.rs b/third_party/rust/static_assertions/src/assert_obj_safe.rs new file mode 100644 index 0000000000..ecbba96475 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_obj_safe.rs @@ -0,0 +1,76 @@ +// FIXME: Link below is required to render in index +/// Asserts that the traits support dynamic dispatch +/// ([object-safety](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects)). +/// +/// This is useful for when changes are made to a trait that accidentally +/// prevent it from being used as an [object]. Such a case would be adding a +/// generic method and forgetting to add `where Self: Sized` after it. If left +/// unnoticed, that mistake will affect crate users and break both forward and +/// backward compatibility. +/// +/// # Examples +/// +/// When exposing a public API, it's important that traits that could previously +/// use dynamic dispatch can still do so in future compatible crate versions. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// trait MySafeTrait { +/// fn foo(&self) -> u32; +/// } +/// +/// assert_obj_safe!(std::fmt::Write, MySafeTrait); +/// ``` +/// +/// Works with traits that are not in the calling module: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// mod inner { +/// pub trait BasicTrait { +/// fn bar(&self); +/// } +/// assert_obj_safe!(BasicTrait); +/// } +/// +/// assert_obj_safe!(inner::BasicTrait); +/// ``` +/// +/// The following example fails to compile because raw pointers cannot be sent +/// between threads safely: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl!(*const u8, Send); +/// ``` +/// +/// The following example fails to compile because generics without +/// `where Self: Sized` are not allowed in [object-safe][object] trait methods: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// trait MyUnsafeTrait { +/// fn baz<T>(&self) -> T; +/// } +/// +/// assert_obj_safe!(MyUnsafeTrait); +/// ``` +/// +/// When we fix that, the previous code will compile: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// trait MyUnsafeTrait { +/// fn baz<T>(&self) -> T where Self: Sized; +/// } +/// +/// assert_obj_safe!(MyUnsafeTrait); +/// ``` +/// +/// [object]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects +#[macro_export] +macro_rules! assert_obj_safe { + ($($xs:path),+ $(,)?) => { + $(const _: Option<&$xs> = None;)+ + }; +} diff --git a/third_party/rust/static_assertions/src/assert_trait.rs b/third_party/rust/static_assertions/src/assert_trait.rs new file mode 100644 index 0000000000..c231492fda --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_trait.rs @@ -0,0 +1,105 @@ +/// Asserts that the trait is a child of all of the other traits. +/// +/// Related: +/// - [`assert_trait_super_all!`] +/// +/// # Examples +/// +/// All types that implement [`Copy`] must implement [`Clone`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_trait_sub_all!(Copy: Clone); +/// ``` +/// +/// All types that implement [`Ord`] must implement [`PartialEq`], [`Eq`], and +/// [`PartialOrd`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_trait_sub_all!(Ord: PartialEq, Eq, PartialOrd); +/// ``` +/// +/// The following example fails to compile because [`Eq`] is not required for +/// [`PartialOrd`]: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_trait_sub_all!(PartialOrd: Eq); +/// ``` +/// +/// [`assert_trait_super_all!`]: macro.assert_trait_super_all.html +/// +/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html +/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +/// [`Ord`]: https://doc.rust-lang.org/std/cmp/trait.Ord.html +/// [`PartialOrd`]: https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html +/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html +/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html +#[macro_export] +macro_rules! assert_trait_sub_all { + ($sub:path: $($super:path),+ $(,)?) => { + const _: () = { + // One scope per super-trait. + $({ + #[allow(non_camel_case_types)] + trait __Impl_Implication: $super {} + + // Can only be implemented for `$sub` types if `$super` is + // also implemented. + impl<T: $sub> __Impl_Implication for T {} + })+ + }; + }; +} + +/// Asserts that the trait is a parent of all of the other traits. +/// +/// Related: +/// - [`assert_trait_sub_all!`] +/// +/// # Examples +/// +/// With this, traits `A` and `B` can both be tested to require [`Copy`] on a +/// single line: +/// +/// ``` +/// # use static_assertions::assert_trait_super_all; +/// trait A: Copy {} +/// trait B: Copy {} +/// +/// assert_trait_super_all!(Copy: A, B); +/// ``` +/// +/// Otherwise, each sub-trait would require its own call to +/// [`assert_trait_sub_all!`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # trait A: Copy {} +/// # trait B: Copy {} +/// assert_trait_sub_all!(A: Copy); +/// assert_trait_sub_all!(B: Copy); +/// ``` +/// +/// The following example fails to compile because trait `C` does not require +/// [`Copy`]: +/// +/// ```compile_fail +/// # use static_assertions::assert_trait_super_all; +/// # trait A: Copy {} +/// # trait B: Copy {} +/// trait C {} +/// +/// assert_trait_super_all!(Copy: A, B, C); +/// ``` +/// +/// [`assert_trait_sub_all!`]: macro.assert_trait_sub_all.html +/// +/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html +#[macro_export(local_inner_macros)] +macro_rules! assert_trait_super_all { + ($super:path: $($sub:path),+ $(,)?) => { + $(assert_trait_sub_all!($sub: $super);)+ + }; +} diff --git a/third_party/rust/static_assertions/src/assert_type.rs b/third_party/rust/static_assertions/src/assert_type.rs new file mode 100644 index 0000000000..dd2dc2a6f7 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_type.rs @@ -0,0 +1,101 @@ +/// Asserts that _all_ types in a list are equal to each other. +/// +/// # Examples +/// +/// Often times, type aliases are used to express usage semantics via naming. In +/// some cases, the underlying type may differ based on platform. However, other +/// types like [`c_float`] will always alias the same type. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::os::raw::c_float; +/// +/// assert_type_eq_all!(c_float, f32); +/// ``` +/// +/// This macro can also be used to compare types that involve lifetimes! Just +/// use `'static` in that case: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// type Buf<'a> = &'a [u8]; +/// +/// assert_type_eq_all!(Buf<'static>, &'static [u8]); +/// # } +/// ``` +/// +/// The following example fails to compile because `String` and `str` do not +/// refer to the same type: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_type_eq_all!(String, str); +/// ``` +/// +/// This should also work the other way around, regardless of [`Deref`] +/// implementations. +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_type_eq_all!(str, String); +/// ``` +/// +/// [`c_float`]: https://doc.rust-lang.org/std/os/raw/type.c_float.html +/// [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html +#[macro_export] +macro_rules! assert_type_eq_all { + ($x:ty, $($xs:ty),+ $(,)*) => { + const _: fn() = || { $({ + trait TypeEq { + type This: ?Sized; + } + + impl<T: ?Sized> TypeEq for T { + type This = Self; + } + + fn assert_type_eq_all<T, U>() + where + T: ?Sized + TypeEq<This = U>, + U: ?Sized, + {} + + assert_type_eq_all::<$x, $xs>(); + })+ }; + }; +} + +/// Asserts that _all_ types are **not** equal to each other. +/// +/// # Examples +/// +/// Rust has all sorts of slices, but they represent different types of data: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_type_ne_all!([u8], [u16], str); +/// ``` +/// +/// The following example fails to compile because [`c_uchar`] is a type alias +/// for [`u8`]: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::os::raw::c_uchar; +/// +/// assert_type_ne_all!(c_uchar, u8, u32); +/// ``` +/// +/// [`c_uchar`]: https://doc.rust-lang.org/std/os/raw/type.c_uchar.html +/// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html +#[macro_export] +macro_rules! assert_type_ne_all { + ($x:ty, $($y:ty),+ $(,)?) => { + const _: fn() = || { + trait MutuallyExclusive {} + impl MutuallyExclusive for $x {} + $(impl MutuallyExclusive for $y {})+ + }; + }; +} diff --git a/third_party/rust/static_assertions/src/const_assert.rs b/third_party/rust/static_assertions/src/const_assert.rs new file mode 100644 index 0000000000..16ae4a6b42 --- /dev/null +++ b/third_party/rust/static_assertions/src/const_assert.rs @@ -0,0 +1,109 @@ +/// Asserts that constant expressions evaluate to `true`. +/// +/// Constant expressions can be ensured to have certain properties via this +/// macro If the expression evaluates to `false`, the file will fail to compile. +/// This is synonymous to [`static_assert` in C++][static_assert]. +/// +/// # Alternatives +/// +/// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for +/// validating whether a sequence of expressions are equal to one another. +/// +/// # Examples +/// +/// A common use case is to guarantee properties about a constant value that's +/// generated via meta-programming. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const VALUE: i32 = // ... +/// # 3; +/// +/// const_assert!(VALUE >= 2); +/// ``` +/// +/// Inputs are type-checked as booleans: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert!(!0); +/// ``` +/// +/// Despite this being a macro, we see this produces a type error: +/// +/// ```txt +/// | const_assert!(!0); +/// | ^^ expected bool, found integral variable +/// | +/// = note: expected type `bool` +/// found type `{integer}` +/// ``` +/// +/// The following fails to compile because multiplying by 5 does not have an +/// identity property: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert!(5 * 5 == 5); +/// ``` +/// +/// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert +#[macro_export] +macro_rules! const_assert { + ($x:expr $(,)?) => { + #[allow(unknown_lints, eq_op)] + const _: [(); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize] = []; + }; +} + +/// Asserts that constants are equal in value. +/// +/// # Examples +/// +/// This works as a shorthand for `const_assert!(a == b)`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const TWO: usize = 2; +/// +/// const_assert_eq!(TWO * TWO, TWO + TWO); +/// ``` +/// +/// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert_eq!(4 + 4, 4 * 4); +/// ``` +#[macro_export(local_inner_macros)] +macro_rules! const_assert_eq { + ($x:expr, $y:expr $(,)?) => { + const_assert!($x == $y); + }; +} + +/// Asserts that constants are **not** equal in value. +/// +/// # Examples +/// +/// This works as a shorthand for `const_assert!(a != b)`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const NUM: usize = 32; +/// +/// const_assert_ne!(NUM * NUM, 64); +/// ``` +/// +/// The following example fails to compile because 2 is magic and 2 × 2 = 2 + 2: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert_ne!(2 + 2, 2 * 2); +/// ``` +#[macro_export(local_inner_macros)] +macro_rules! const_assert_ne { + ($x:expr, $y:expr $(,)?) => { + const_assert!($x != $y); + }; +} diff --git a/third_party/rust/static_assertions/src/lib.rs b/third_party/rust/static_assertions/src/lib.rs new file mode 100644 index 0000000000..a43cc1f56d --- /dev/null +++ b/third_party/rust/static_assertions/src/lib.rs @@ -0,0 +1,97 @@ +//! [![Banner](https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Banner.png)](https://github.com/nvzqz/static-assertions-rs) +//! +//! <div align="center"> +//! <a href="https://crates.io/crates/static_assertions"> +//! <img src="https://img.shields.io/crates/d/static_assertions.svg" alt="Downloads"> +//! </a> +//! <a href="https://travis-ci.org/nvzqz/static-assertions-rs"> +//! <img src="https://travis-ci.org/nvzqz/static-assertions-rs.svg?branch=master" alt="Build Status"> +//! </a> +//! <img src="https://img.shields.io/badge/rustc-^1.37.0-blue.svg" alt="rustc ^1.37.0"> +//! <br><br> +//! </div> +//! +//! Assertions to ensure correct assumptions about constants, types, and more. +//! +//! _All_ checks provided by this crate are performed at [compile-time]. This +//! allows for finding errors quickly and early when it comes to ensuring +//! certain features or aspects of a codebase. These macros are especially +//! important when exposing a public API that requires types to be the same size +//! or implement certain traits. +//! +//! # Usage +//! +//! This crate is available [on crates.io][crate] and can be used by adding the +//! following to your project's [`Cargo.toml`]: +//! +//! ```toml +//! [dependencies] +//! static_assertions = "1.1.0" +//! ``` +//! +//! and this to your crate root (`main.rs` or `lib.rs`): +//! +//! ``` +//! #[macro_use] +//! extern crate static_assertions; +//! # fn main() {} +//! ``` +//! +//! When using [Rust 2018 edition][2018], the following shorthand can help if +//! having `#[macro_use]` is undesirable. +//! +//! ```edition2018 +//! extern crate static_assertions as sa; +//! +//! sa::const_assert!(true); +//! ``` +//! +//! # Examples +//! +//! Very thorough examples are provided in the docs for +//! [each individual macro](#macros). Failure case examples are also documented. +//! +//! # Changes +//! +//! See [`CHANGELOG.md`](https://github.com/nvzqz/static-assertions-rs/blob/master/CHANGELOG.md) +//! for an exhaustive list of what has changed from one version to another. +//! +//! # Donate +//! +//! This project is made freely available (as in free beer), but unfortunately +//! not all beer is free! So, if you would like to buy me a beer (or coffee or +//! *more*), then consider supporting my work that's benefited your project +//! and thousands of others. +//! +//! <a href="https://www.patreon.com/nvzqz"> +//! <img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patron!" height="35"> +//! </a> +//! <a href="https://www.paypal.me/nvzqz"> +//! <img src="https://buymecoffee.intm.org/img/button-paypal-white.png" alt="Buy me a coffee" height="35"> +//! </a> +//! +//! [Rust 1.37]: https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html +//! [2018]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#rust-2018 +//! [crate]: https://crates.io/crates/static_assertions +//! [compile-time]: https://en.wikipedia.org/wiki/Compile_time +//! [`Cargo.toml`]: https://doc.rust-lang.org/cargo/reference/manifest.html + +#![doc(html_root_url = "https://docs.rs/static_assertions/1.1.0")] +#![doc(html_logo_url = "https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Icon.png")] + +#![no_std] + +#![deny(unused_macros)] + +#[doc(hidden)] +pub extern crate core as _core; + +mod assert_cfg; +mod assert_eq_align; +mod assert_eq_size; +mod assert_fields; +mod assert_impl; +mod assert_obj_safe; +mod assert_trait; +mod assert_type; +mod const_assert; |