Skip to content

Commit 2205c3f

Browse files
committed
Add a macro to conveniently implement marker traits
1 parent 7234d63 commit 2205c3f

File tree

2 files changed

+114
-108
lines changed

2 files changed

+114
-108
lines changed

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
#![feature(const_waker)]
163163
#![feature(core_panic)]
164164
#![feature(duration_consts_float)]
165+
#![feature(internal_impls_macro)]
165166
#![feature(ip)]
166167
#![feature(is_ascii_octdigit)]
167168
#![feature(maybe_uninit_uninit_array)]

library/core/src/marker.rs

Lines changed: 113 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,60 @@ use crate::fmt::Debug;
1212
use crate::hash::Hash;
1313
use crate::hash::Hasher;
1414

15+
/// Implements a given marker trait for multiple types at the same time.
16+
///
17+
/// The basic syntax looks like this:
18+
/// ```ignore private macro
19+
/// marker_impls! { MarkerTrait for u8, i8 }
20+
/// ```
21+
/// You can also implement `unsafe` traits
22+
/// ```ignore private macro
23+
/// marker_impls! { unsafe MarkerTrait for u8, i8 }
24+
/// ```
25+
/// Add attributes to all impls:
26+
/// ```ignore private macro
27+
/// marker_impls! {
28+
/// #[allow(lint)]
29+
/// #[unstable(feature = "marker_trait", issue = "none")]
30+
/// MarkerTrait for u8, i8
31+
/// }
32+
/// ```
33+
/// And use generics:
34+
/// ```ignore private macro
35+
/// marker_impls! {
36+
/// MarkerTrait for
37+
/// u8, i8,
38+
/// {T: ?Sized} *const T,
39+
/// {T: ?Sized} *mut T,
40+
/// {T: MarkerTrait} PhantomData<T>,
41+
/// u32,
42+
/// }
43+
/// ```
44+
#[unstable(feature = "internal_impls_macro", issue = "none")]
45+
macro marker_impls {
46+
( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
47+
// This inner macro is needed because... idk macros are weird.
48+
// It allows repeating `meta` on all impls.
49+
#[unstable(feature = "internal_impls_macro", issue = "none")]
50+
macro _impl {
51+
( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
52+
$(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
53+
}
54+
}
55+
$( _impl! { $({$($bounds)*})? $T } )+
56+
},
57+
( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
58+
#[unstable(feature = "internal_impls_macro", issue = "none")]
59+
macro _impl {
60+
( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
61+
$(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
62+
}
63+
}
64+
65+
$( _impl! { $({$($bounds)*})? $T } )+
66+
},
67+
}
68+
1569
/// Types that can be transferred across thread boundaries.
1670
///
1771
/// This trait is automatically implemented when the compiler determines it's
@@ -214,34 +268,14 @@ pub trait StructuralEq {
214268
// Empty.
215269
}
216270

217-
#[unstable(feature = "structural_match", issue = "31434")]
218-
impl StructuralEq for usize {}
219-
#[unstable(feature = "structural_match", issue = "31434")]
220-
impl StructuralEq for u8 {}
221-
#[unstable(feature = "structural_match", issue = "31434")]
222-
impl StructuralEq for u16 {}
223-
#[unstable(feature = "structural_match", issue = "31434")]
224-
impl StructuralEq for u32 {}
225-
#[unstable(feature = "structural_match", issue = "31434")]
226-
impl StructuralEq for u64 {}
227-
#[unstable(feature = "structural_match", issue = "31434")]
228-
impl StructuralEq for u128 {}
229-
#[unstable(feature = "structural_match", issue = "31434")]
230-
impl StructuralEq for isize {}
231-
#[unstable(feature = "structural_match", issue = "31434")]
232-
impl StructuralEq for i8 {}
233-
#[unstable(feature = "structural_match", issue = "31434")]
234-
impl StructuralEq for i16 {}
235-
#[unstable(feature = "structural_match", issue = "31434")]
236-
impl StructuralEq for i32 {}
237-
#[unstable(feature = "structural_match", issue = "31434")]
238-
impl StructuralEq for i64 {}
239-
#[unstable(feature = "structural_match", issue = "31434")]
240-
impl StructuralEq for i128 {}
241-
#[unstable(feature = "structural_match", issue = "31434")]
242-
impl StructuralEq for bool {}
243-
#[unstable(feature = "structural_match", issue = "31434")]
244-
impl StructuralEq for char {}
271+
marker_impls! {
272+
#[unstable(feature = "structural_match", issue = "31434")]
273+
StructuralEq for
274+
usize, u8, u16, u32, u64, u128,
275+
isize, i8, i16, i32, i64, i128,
276+
bool,
277+
char,
278+
}
245279

246280
/// Types whose values can be duplicated simply by copying bits.
247281
///
@@ -430,6 +464,30 @@ pub macro Copy($item:item) {
430464
/* compiler built-in */
431465
}
432466

467+
// Implementations of `Copy` for primitive types.
468+
//
469+
// Implementations that cannot be described in Rust
470+
// are implemented in `traits::SelectionContext::copy_clone_conditions()`
471+
// in `rustc_trait_selection`.
472+
marker_impls! {
473+
#[stable(feature = "rust1", since = "1.0.0")]
474+
Copy for
475+
usize, u8, u16, u32, u64, u128,
476+
isize, i8, i16, i32, i64, i128,
477+
f32, f64,
478+
bool, char,
479+
{T: ?Sized} *const T,
480+
{T: ?Sized} *mut T,
481+
482+
}
483+
484+
#[unstable(feature = "never_type", issue = "35121")]
485+
impl Copy for ! {}
486+
487+
/// Shared references can be copied, but mutable references *cannot*!
488+
#[stable(feature = "rust1", since = "1.0.0")]
489+
impl<T: ?Sized> Copy for &T {}
490+
433491
/// Types for which it is safe to share references between threads.
434492
///
435493
/// This trait is automatically implemented when the compiler determines
@@ -802,11 +860,14 @@ pub trait DiscriminantKind {
802860
pub(crate) unsafe auto trait Freeze {}
803861

804862
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
805-
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
806-
unsafe impl<T: ?Sized> Freeze for *const T {}
807-
unsafe impl<T: ?Sized> Freeze for *mut T {}
808-
unsafe impl<T: ?Sized> Freeze for &T {}
809-
unsafe impl<T: ?Sized> Freeze for &mut T {}
863+
marker_impls! {
864+
unsafe Freeze for
865+
{T: ?Sized} PhantomData<T>,
866+
{T: ?Sized} *const T,
867+
{T: ?Sized} *mut T,
868+
{T: ?Sized} &T,
869+
{T: ?Sized} &mut T,
870+
}
810871

811872
/// Types that can be safely moved after being pinned.
812873
///
@@ -867,17 +928,19 @@ pub struct PhantomPinned;
867928
#[stable(feature = "pin", since = "1.33.0")]
868929
impl !Unpin for PhantomPinned {}
869930

870-
#[stable(feature = "pin", since = "1.33.0")]
871-
impl<'a, T: ?Sized + 'a> Unpin for &'a T {}
872-
873-
#[stable(feature = "pin", since = "1.33.0")]
874-
impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {}
875-
876-
#[stable(feature = "pin_raw", since = "1.38.0")]
877-
impl<T: ?Sized> Unpin for *const T {}
931+
marker_impls! {
932+
#[stable(feature = "pin", since = "1.33.0")]
933+
Unpin for
934+
{T: ?Sized} &T,
935+
{T: ?Sized} &mut T,
936+
}
878937

879-
#[stable(feature = "pin_raw", since = "1.38.0")]
880-
impl<T: ?Sized> Unpin for *mut T {}
938+
marker_impls! {
939+
#[stable(feature = "pin_raw", since = "1.38.0")]
940+
Unpin for
941+
{T: ?Sized} *const T,
942+
{T: ?Sized} *mut T,
943+
}
881944

882945
/// A marker for types that can be dropped.
883946
///
@@ -917,72 +980,14 @@ pub trait PointerLike {}
917980
#[unstable(feature = "adt_const_params", issue = "95174")]
918981
#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
919982
pub trait ConstParamTy: StructuralEq {}
920-
#[unstable(feature = "adt_const_params", issue = "95174")]
921-
impl ConstParamTy for usize {}
922-
#[unstable(feature = "adt_const_params", issue = "95174")]
923-
impl ConstParamTy for u8 {}
924-
#[unstable(feature = "adt_const_params", issue = "95174")]
925-
impl ConstParamTy for u16 {}
926-
#[unstable(feature = "adt_const_params", issue = "95174")]
927-
impl ConstParamTy for u32 {}
928-
#[unstable(feature = "adt_const_params", issue = "95174")]
929-
impl ConstParamTy for u64 {}
930-
#[unstable(feature = "adt_const_params", issue = "95174")]
931-
impl ConstParamTy for u128 {}
932-
#[unstable(feature = "adt_const_params", issue = "95174")]
933-
impl ConstParamTy for isize {}
934-
#[unstable(feature = "adt_const_params", issue = "95174")]
935-
impl ConstParamTy for i8 {}
936-
#[unstable(feature = "adt_const_params", issue = "95174")]
937-
impl ConstParamTy for i16 {}
938-
#[unstable(feature = "adt_const_params", issue = "95174")]
939-
impl ConstParamTy for i32 {}
940-
#[unstable(feature = "adt_const_params", issue = "95174")]
941-
impl ConstParamTy for i64 {}
942-
#[unstable(feature = "adt_const_params", issue = "95174")]
943-
impl ConstParamTy for i128 {}
944-
#[unstable(feature = "adt_const_params", issue = "95174")]
945-
impl ConstParamTy for bool {}
946-
#[unstable(feature = "adt_const_params", issue = "95174")]
947-
impl ConstParamTy for char {}
948-
949-
/// Implementations of `Copy` for primitive types.
950-
///
951-
/// Implementations that cannot be described in Rust
952-
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
953-
/// in `rustc_trait_selection`.
954-
mod copy_impls {
955-
956-
use super::Copy;
957-
958-
macro_rules! impl_copy {
959-
($($t:ty)*) => {
960-
$(
961-
#[stable(feature = "rust1", since = "1.0.0")]
962-
impl Copy for $t {}
963-
)*
964-
}
965-
}
966983

967-
impl_copy! {
968-
usize u8 u16 u32 u64 u128
969-
isize i8 i16 i32 i64 i128
970-
f32 f64
971-
bool char
972-
}
973-
974-
#[unstable(feature = "never_type", issue = "35121")]
975-
impl Copy for ! {}
976-
977-
#[stable(feature = "rust1", since = "1.0.0")]
978-
impl<T: ?Sized> Copy for *const T {}
979-
980-
#[stable(feature = "rust1", since = "1.0.0")]
981-
impl<T: ?Sized> Copy for *mut T {}
982-
983-
/// Shared references can be copied, but mutable references *cannot*!
984-
#[stable(feature = "rust1", since = "1.0.0")]
985-
impl<T: ?Sized> Copy for &T {}
984+
marker_impls! {
985+
#[unstable(feature = "adt_const_params", issue = "95174")]
986+
ConstParamTy for
987+
usize, u8, u16, u32, u64, u128,
988+
isize, i8, i16, i32, i64, i128,
989+
bool,
990+
char,
986991
}
987992

988993
/// A common trait implemented by all function pointers.

0 commit comments

Comments
 (0)