From 2205c3fa5ffdb8794917d541e580742f527be8f1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 11:29:21 +0000 Subject: [PATCH] Add a macro to conveniently implement marker traits --- library/core/src/lib.rs | 1 + library/core/src/marker.rs | 221 +++++++++++++++++++------------------ 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 24a9d81d037..b269a3bcb00 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -162,6 +162,7 @@ #![feature(const_waker)] #![feature(core_panic)] #![feature(duration_consts_float)] +#![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] #![feature(maybe_uninit_uninit_array)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 24e95aed27e..8c240661b2b 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -12,6 +12,60 @@ use crate::fmt::Debug; use crate::hash::Hash; use crate::hash::Hasher; +/// Implements a given marker trait for multiple types at the same time. +/// +/// The basic syntax looks like this: +/// ```ignore private macro +/// marker_impls! { MarkerTrait for u8, i8 } +/// ``` +/// You can also implement `unsafe` traits +/// ```ignore private macro +/// marker_impls! { unsafe MarkerTrait for u8, i8 } +/// ``` +/// Add attributes to all impls: +/// ```ignore private macro +/// marker_impls! { +/// #[allow(lint)] +/// #[unstable(feature = "marker_trait", issue = "none")] +/// MarkerTrait for u8, i8 +/// } +/// ``` +/// And use generics: +/// ```ignore private macro +/// marker_impls! { +/// MarkerTrait for +/// u8, i8, +/// {T: ?Sized} *const T, +/// {T: ?Sized} *mut T, +/// {T: MarkerTrait} PhantomData, +/// u32, +/// } +/// ``` +#[unstable(feature = "internal_impls_macro", issue = "none")] +macro marker_impls { + ( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => { + // This inner macro is needed because... idk macros are weird. + // It allows repeating `meta` on all impls. + #[unstable(feature = "internal_impls_macro", issue = "none")] + macro _impl { + ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => { + $(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {} + } + } + $( _impl! { $({$($bounds)*})? $T } )+ + }, + ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => { + #[unstable(feature = "internal_impls_macro", issue = "none")] + macro _impl { + ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => { + $(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {} + } + } + + $( _impl! { $({$($bounds)*})? $T } )+ + }, +} + /// Types that can be transferred across thread boundaries. /// /// This trait is automatically implemented when the compiler determines it's @@ -214,34 +268,14 @@ pub trait StructuralEq { // Empty. } -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for usize {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u8 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u16 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u32 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u64 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u128 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for isize {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i8 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i16 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i32 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i64 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i128 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for bool {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for char {} +marker_impls! { + #[unstable(feature = "structural_match", issue = "31434")] + StructuralEq for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, +} /// Types whose values can be duplicated simply by copying bits. /// @@ -430,6 +464,30 @@ pub macro Copy($item:item) { /* compiler built-in */ } +// Implementations of `Copy` for primitive types. +// +// Implementations that cannot be described in Rust +// are implemented in `traits::SelectionContext::copy_clone_conditions()` +// in `rustc_trait_selection`. +marker_impls! { + #[stable(feature = "rust1", since = "1.0.0")] + Copy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + f32, f64, + bool, char, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Copy for ! {} + +/// Shared references can be copied, but mutable references *cannot*! +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for &T {} + /// Types for which it is safe to share references between threads. /// /// This trait is automatically implemented when the compiler determines @@ -802,11 +860,14 @@ pub trait DiscriminantKind { pub(crate) unsafe auto trait Freeze {} impl !Freeze for UnsafeCell {} -unsafe impl Freeze for PhantomData {} -unsafe impl Freeze for *const T {} -unsafe impl Freeze for *mut T {} -unsafe impl Freeze for &T {} -unsafe impl Freeze for &mut T {} +marker_impls! { + unsafe Freeze for + {T: ?Sized} PhantomData, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} /// Types that can be safely moved after being pinned. /// @@ -867,17 +928,19 @@ pub struct PhantomPinned; #[stable(feature = "pin", since = "1.33.0")] impl !Unpin for PhantomPinned {} -#[stable(feature = "pin", since = "1.33.0")] -impl<'a, T: ?Sized + 'a> Unpin for &'a T {} +marker_impls! { + #[stable(feature = "pin", since = "1.33.0")] + Unpin for + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} -#[stable(feature = "pin", since = "1.33.0")] -impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {} - -#[stable(feature = "pin_raw", since = "1.38.0")] -impl Unpin for *const T {} - -#[stable(feature = "pin_raw", since = "1.38.0")] -impl Unpin for *mut T {} +marker_impls! { + #[stable(feature = "pin_raw", since = "1.38.0")] + Unpin for + {T: ?Sized} *const T, + {T: ?Sized} *mut T, +} /// A marker for types that can be dropped. /// @@ -917,72 +980,14 @@ pub trait PointerLike {} #[unstable(feature = "adt_const_params", issue = "95174")] #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] pub trait ConstParamTy: StructuralEq {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for usize {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u8 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u16 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u32 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u64 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u128 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for isize {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i8 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i16 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i32 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i64 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i128 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for bool {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for char {} -/// Implementations of `Copy` for primitive types. -/// -/// Implementations that cannot be described in Rust -/// are implemented in `traits::SelectionContext::copy_clone_conditions()` -/// in `rustc_trait_selection`. -mod copy_impls { - - use super::Copy; - - macro_rules! impl_copy { - ($($t:ty)*) => { - $( - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for $t {} - )* - } - } - - impl_copy! { - usize u8 u16 u32 u64 u128 - isize i8 i16 i32 i64 i128 - f32 f64 - bool char - } - - #[unstable(feature = "never_type", issue = "35121")] - impl Copy for ! {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for *const T {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for *mut T {} - - /// Shared references can be copied, but mutable references *cannot*! - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for &T {} +marker_impls! { + #[unstable(feature = "adt_const_params", issue = "95174")] + ConstParamTy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, } /// A common trait implemented by all function pointers.