Skip to content

Commit 2b8d27b

Browse files
committed
Switch impl_tag! from explicit tags to ${index()}
1 parent ad8c7b6 commit 2b8d27b

File tree

5 files changed

+57
-51
lines changed

5 files changed

+57
-51
lines changed

compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(unwrap_infallible)]
3232
#![feature(strict_provenance)]
3333
#![feature(ptr_alignment_type)]
34+
#![feature(macro_metavar_expr)]
3435
#![allow(rustc::default_hash_types)]
3536
#![allow(rustc::potential_query_instability)]
3637
#![deny(rustc::untranslatable_diagnostic)]

compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs

+31-28
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/// Basic usage:
1212
///
1313
/// ```
14+
/// #![feature(macro_metavar_expr)]
1415
/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag};
1516
///
1617
/// #[derive(Copy, Clone, PartialEq, Debug)]
@@ -24,19 +25,20 @@
2425
/// impl_tag! {
2526
/// // The type for which the `Tag` will be implemented
2627
/// impl Tag for SomeTag;
27-
/// // You need to specify the `{value_of_the_type} <=> {tag}` relationship
28-
/// SomeTag::A <=> 0,
29-
/// SomeTag::B <=> 1,
28+
/// // You need to specify all possible tag values:
29+
/// SomeTag::A, // 0
30+
/// SomeTag::B, // 1
3031
/// // For variants with fields, you need to specify the fields:
31-
/// SomeTag::X { v: true } <=> 2,
32-
/// SomeTag::X { v: false } <=> 3,
32+
/// SomeTag::X { v: true }, // 2
33+
/// SomeTag::X { v: false }, // 3
3334
/// // For tuple variants use named syntax:
34-
/// SomeTag::Y { 0: true, 1: true } <=> 4,
35-
/// SomeTag::Y { 0: false, 1: true } <=> 5,
36-
/// SomeTag::Y { 0: true, 1: false } <=> 6,
37-
/// SomeTag::Y { 0: false, 1: false } <=> 7,
35+
/// SomeTag::Y { 0: true, 1: true }, // 4
36+
/// SomeTag::Y { 0: false, 1: true }, // 5
37+
/// SomeTag::Y { 0: true, 1: false }, // 6
38+
/// SomeTag::Y { 0: false, 1: false }, // 7
3839
/// }
3940
///
41+
/// // Tag values are assigned in order:
4042
/// assert_eq!(SomeTag::A.into_usize(), 0);
4143
/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3);
4244
/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5);
@@ -49,22 +51,24 @@
4951
/// Structs are supported:
5052
///
5153
/// ```
54+
/// #![feature(macro_metavar_expr)]
5255
/// # use rustc_data_structures::impl_tag;
5356
/// #[derive(Copy, Clone)]
5457
/// struct Flags { a: bool, b: bool }
5558
///
5659
/// impl_tag! {
5760
/// impl Tag for Flags;
58-
/// Flags { a: true, b: true } <=> 3,
59-
/// Flags { a: false, b: true } <=> 2,
60-
/// Flags { a: true, b: false } <=> 1,
61-
/// Flags { a: false, b: false } <=> 0,
61+
/// Flags { a: true, b: true },
62+
/// Flags { a: false, b: true },
63+
/// Flags { a: true, b: false },
64+
/// Flags { a: false, b: false },
6265
/// }
6366
/// ```
6467
///
6568
/// Not specifying all values results in a compile error:
6669
///
6770
/// ```compile_fail,E0004
71+
/// #![feature(macro_metavar_expr)]
6872
/// # use rustc_data_structures::impl_tag;
6973
/// #[derive(Copy, Clone)]
7074
/// enum E {
@@ -74,24 +78,26 @@
7478
///
7579
/// impl_tag! {
7680
/// impl Tag for E;
77-
/// E::A <=> 0,
81+
/// E::A,
7882
/// }
7983
/// ```
8084
#[macro_export]
8185
macro_rules! impl_tag {
8286
(
8387
impl Tag for $Self:ty;
8488
$(
85-
$($path:ident)::* $( { $( $fields:tt )* })? <=> $tag:literal,
89+
$($path:ident)::* $( { $( $fields:tt )* })?,
8690
)*
8791
) => {
8892
// Safety:
89-
// `into_usize` only returns one of `$tag`s,
90-
// `bits_for_tags` is called on all `$tag`s,
91-
// thus `BITS` constant is correct.
93+
// `bits_for_tags` is called on the same `${index()}`-es as
94+
// `into_usize` returns, thus `BITS` constant is correct.
9295
unsafe impl $crate::tagged_ptr::Tag for $Self {
9396
const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[
94-
$( $tag, )*
97+
$(
98+
${index()},
99+
$( ${ignore(path)} )*
100+
)*
95101
]);
96102

97103
fn into_usize(self) -> usize {
@@ -101,25 +107,22 @@ macro_rules! impl_tag {
101107
match self {
102108
// `match` is doing heavy lifting here, by requiring exhaustiveness
103109
$(
104-
$($path)::* $( { $( $fields )* } )? => $tag,
110+
$($path)::* $( { $( $fields )* } )? => ${index()},
105111
)*
106112
}
107113
}
108114

109115
unsafe fn from_usize(tag: usize) -> Self {
110-
// Similarly to the above, this forbids repeating tags
111-
// (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>)
112-
#[forbid(unreachable_patterns)]
113116
match tag {
114117
$(
115-
$tag => $($path)::* $( { $( $fields )* } )?,
118+
${index()} => $($path)::* $( { $( $fields )* } )?,
116119
)*
117120

118121
// Safety:
119-
// `into_usize` only returns one of `$tag`s,
120-
// all `$tag`s are filtered up above,
121-
// thus if this is reached, the safety contract of this
122-
// function was already breached.
122+
// `into_usize` only returns `${index()}` of the same
123+
// repetition as we are filtering above, thus if this is
124+
// reached, the safety contract of this function was
125+
// already breached.
123126
_ => unsafe {
124127
debug_assert!(
125128
false,

compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs

+20-19
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,31 @@ fn bits_constant() {
44

55
#[derive(Copy, Clone)]
66
struct Unit;
7-
impl_tag! { impl Tag for Unit; Unit <=> 0, }
7+
impl_tag! { impl Tag for Unit; Unit, }
88
assert_eq!(Unit::BITS, 0);
99

1010
#[derive(Copy, Clone)]
11-
struct Unit1;
12-
impl_tag! { impl Tag for Unit1; Unit1 <=> 1, }
13-
assert_eq!(Unit1::BITS, 1);
14-
15-
#[derive(Copy, Clone)]
16-
struct Unit2;
17-
impl_tag! { impl Tag for Unit2; Unit2 <=> 0b10, }
18-
assert_eq!(Unit2::BITS, 2);
19-
20-
#[derive(Copy, Clone)]
21-
struct Unit3;
22-
impl_tag! { impl Tag for Unit3; Unit3 <=> 0b100, }
23-
assert_eq!(Unit3::BITS, 3);
24-
25-
#[derive(Copy, Clone)]
26-
enum Enum {
11+
enum Enum3 {
2712
A,
2813
B,
2914
C,
3015
}
31-
impl_tag! { impl Tag for Enum; Enum::A <=> 0b1, Enum::B <=> 0b1000, Enum::C <=> 0b10, }
32-
assert_eq!(Enum::BITS, 4);
16+
impl_tag! { impl Tag for Enum3; Enum3::A, Enum3::B, Enum3::C, }
17+
assert_eq!(Enum3::BITS, 2);
18+
19+
#[derive(Copy, Clone)]
20+
struct Eight(bool, bool, bool);
21+
impl_tag! {
22+
impl Tag for Eight;
23+
Eight { 0: true, 1: true, 2: true },
24+
Eight { 0: true, 1: true, 2: false },
25+
Eight { 0: true, 1: false, 2: true },
26+
Eight { 0: true, 1: false, 2: false },
27+
Eight { 0: false, 1: true, 2: true },
28+
Eight { 0: false, 1: true, 2: false },
29+
Eight { 0: false, 1: false, 2: true },
30+
Eight { 0: false, 1: false, 2: false },
31+
}
32+
33+
assert_eq!(Eight::BITS, 3);
3334
}

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#![feature(const_option)]
6161
#![feature(trait_alias)]
6262
#![feature(ptr_alignment_type)]
63+
#![feature(macro_metavar_expr)]
6364
#![recursion_limit = "512"]
6465
#![allow(rustc::potential_query_instability)]
6566

compiler/rustc_middle/src/ty/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1628,10 +1628,10 @@ struct ParamTag {
16281628

16291629
impl_tag! {
16301630
impl Tag for ParamTag;
1631-
ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } <=> 0,
1632-
ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } <=> 1,
1633-
ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } <=> 2,
1634-
ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const } <=> 3,
1631+
ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
1632+
ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
1633+
ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
1634+
ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const },
16351635
}
16361636

16371637
impl<'tcx> fmt::Debug for ParamEnv<'tcx> {

0 commit comments

Comments
 (0)