about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2023-04-24 16:48:37 +0000
committerMaybe Waffle <waffle.lapkin@gmail.com>2023-04-24 16:48:37 +0000
commit2b8d27b402b621d20c7c29c500852c727d4cc8cd (patch)
treeba2467a4141f35c18ed56c3f7174f1ddb834ebd0
parentad8c7b6705d94bdf9293fbfe0c4d386d5f7e81a2 (diff)
downloadrust-2b8d27b402b621d20c7c29c500852c727d4cc8cd.tar.gz
rust-2b8d27b402b621d20c7c29c500852c727d4cc8cd.zip
Switch `impl_tag!` from explicit tags to `${index()}`
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs59
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs39
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
5 files changed, 57 insertions, 51 deletions
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 426d2c4034b..004017ec5f3 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -31,6 +31,7 @@
 #![feature(unwrap_infallible)]
 #![feature(strict_provenance)]
 #![feature(ptr_alignment_type)]
+#![feature(macro_metavar_expr)]
 #![allow(rustc::default_hash_types)]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs
index d263bed9581..0b0c152cc4d 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs
@@ -11,6 +11,7 @@
 /// Basic usage:
 ///
 /// ```
+/// #![feature(macro_metavar_expr)]
 /// use rustc_data_structures::{impl_tag, tagged_ptr::Tag};
 ///
 /// #[derive(Copy, Clone, PartialEq, Debug)]
@@ -24,19 +25,20 @@
 /// impl_tag! {
 ///     // The type for which the `Tag` will be implemented
 ///     impl Tag for SomeTag;
-///     // You need to specify the `{value_of_the_type} <=> {tag}` relationship
-///     SomeTag::A <=> 0,
-///     SomeTag::B <=> 1,
+///     // You need to specify all possible tag values:
+///     SomeTag::A, // 0
+///     SomeTag::B, // 1
 ///     // For variants with fields, you need to specify the fields:
-///     SomeTag::X { v: true  } <=> 2,
-///     SomeTag::X { v: false } <=> 3,
+///     SomeTag::X { v: true  }, // 2
+///     SomeTag::X { v: false }, // 3
 ///     // For tuple variants use named syntax:
-///     SomeTag::Y { 0: true,  1: true  } <=> 4,
-///     SomeTag::Y { 0: false, 1: true  } <=> 5,
-///     SomeTag::Y { 0: true,  1: false } <=> 6,
-///     SomeTag::Y { 0: false, 1: false } <=> 7,
+///     SomeTag::Y { 0: true,  1: true  }, // 4
+///     SomeTag::Y { 0: false, 1: true  }, // 5
+///     SomeTag::Y { 0: true,  1: false }, // 6
+///     SomeTag::Y { 0: false, 1: false }, // 7
 /// }
 ///
+/// // Tag values are assigned in order:
 /// assert_eq!(SomeTag::A.into_usize(), 0);
 /// assert_eq!(SomeTag::X { v: false }.into_usize(), 3);
 /// assert_eq!(SomeTag::Y(false, true).into_usize(), 5);
@@ -49,22 +51,24 @@
 /// Structs are supported:
 ///
 /// ```
+/// #![feature(macro_metavar_expr)]
 /// # use rustc_data_structures::impl_tag;
 /// #[derive(Copy, Clone)]
 /// struct Flags { a: bool, b: bool }
 ///
 /// impl_tag! {
 ///     impl Tag for Flags;
-///     Flags { a: true,  b: true  } <=> 3,
-///     Flags { a: false, b: true  } <=> 2,
-///     Flags { a: true,  b: false } <=> 1,
-///     Flags { a: false, b: false } <=> 0,
+///     Flags { a: true,  b: true  },
+///     Flags { a: false, b: true  },
+///     Flags { a: true,  b: false },
+///     Flags { a: false, b: false },
 /// }
 /// ```
 ///
 /// Not specifying all values results in a compile error:
 ///
 /// ```compile_fail,E0004
+/// #![feature(macro_metavar_expr)]
 /// # use rustc_data_structures::impl_tag;
 /// #[derive(Copy, Clone)]
 /// enum E {
@@ -74,7 +78,7 @@
 ///
 /// impl_tag! {
 ///     impl Tag for E;
-///     E::A <=> 0,
+///     E::A,
 /// }
 /// ```
 #[macro_export]
@@ -82,16 +86,18 @@ macro_rules! impl_tag {
     (
         impl Tag for $Self:ty;
         $(
-            $($path:ident)::* $( { $( $fields:tt )* })? <=> $tag:literal,
+            $($path:ident)::* $( { $( $fields:tt )* })?,
         )*
     ) => {
         // Safety:
-        // `into_usize` only returns one of `$tag`s,
-        // `bits_for_tags` is called on all `$tag`s,
-        // thus `BITS` constant is correct.
+        // `bits_for_tags` is called on the same `${index()}`-es as
+        // `into_usize` returns, thus `BITS` constant is correct.
         unsafe impl $crate::tagged_ptr::Tag for $Self {
             const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[
-                $( $tag, )*
+                $(
+                    ${index()},
+                    $( ${ignore(path)} )*
+                )*
             ]);
 
             fn into_usize(self) -> usize {
@@ -101,25 +107,22 @@ macro_rules! impl_tag {
                 match self {
                     // `match` is doing heavy lifting here, by requiring exhaustiveness
                     $(
-                        $($path)::* $( { $( $fields )* } )? => $tag,
+                        $($path)::* $( { $( $fields )* } )? => ${index()},
                     )*
                 }
             }
 
             unsafe fn from_usize(tag: usize) -> Self {
-                // Similarly to the above, this forbids repeating tags
-                // (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>)
-                #[forbid(unreachable_patterns)]
                 match tag {
                     $(
-                        $tag => $($path)::* $( { $( $fields )* } )?,
+                        ${index()} => $($path)::* $( { $( $fields )* } )?,
                     )*
 
                     // Safety:
-                    // `into_usize` only returns one of `$tag`s,
-                    // all `$tag`s are filtered up above,
-                    // thus if this is reached, the safety contract of this
-                    // function was already breached.
+                    // `into_usize` only returns `${index()}` of the same
+                    // repetition as we are filtering above, thus if this is
+                    // reached, the safety contract of this function was
+                    // already breached.
                     _ => unsafe {
                         debug_assert!(
                             false,
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs
index cd19b30ff53..62c926153e1 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs
@@ -4,30 +4,31 @@ fn bits_constant() {
 
     #[derive(Copy, Clone)]
     struct Unit;
-    impl_tag! { impl Tag for Unit; Unit <=> 0, }
+    impl_tag! { impl Tag for Unit; Unit, }
     assert_eq!(Unit::BITS, 0);
 
     #[derive(Copy, Clone)]
-    struct Unit1;
-    impl_tag! { impl Tag for Unit1; Unit1 <=> 1, }
-    assert_eq!(Unit1::BITS, 1);
-
-    #[derive(Copy, Clone)]
-    struct Unit2;
-    impl_tag! { impl Tag for Unit2; Unit2 <=> 0b10, }
-    assert_eq!(Unit2::BITS, 2);
-
-    #[derive(Copy, Clone)]
-    struct Unit3;
-    impl_tag! { impl Tag for Unit3; Unit3 <=> 0b100, }
-    assert_eq!(Unit3::BITS, 3);
-
-    #[derive(Copy, Clone)]
-    enum Enum {
+    enum Enum3 {
         A,
         B,
         C,
     }
-    impl_tag! { impl Tag for Enum; Enum::A <=> 0b1, Enum::B <=> 0b1000, Enum::C <=> 0b10, }
-    assert_eq!(Enum::BITS, 4);
+    impl_tag! { impl Tag for Enum3; Enum3::A, Enum3::B, Enum3::C, }
+    assert_eq!(Enum3::BITS, 2);
+
+    #[derive(Copy, Clone)]
+    struct Eight(bool, bool, bool);
+    impl_tag! {
+        impl Tag for Eight;
+        Eight { 0: true,  1: true,  2: true  },
+        Eight { 0: true,  1: true,  2: false },
+        Eight { 0: true,  1: false, 2: true  },
+        Eight { 0: true,  1: false, 2: false },
+        Eight { 0: false, 1: true,  2: true  },
+        Eight { 0: false, 1: true,  2: false },
+        Eight { 0: false, 1: false, 2: true  },
+        Eight { 0: false, 1: false, 2: false },
+    }
+
+    assert_eq!(Eight::BITS, 3);
 }
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 76a8367b2c4..e9172e767e0 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -60,6 +60,7 @@
 #![feature(const_option)]
 #![feature(trait_alias)]
 #![feature(ptr_alignment_type)]
+#![feature(macro_metavar_expr)]
 #![recursion_limit = "512"]
 #![allow(rustc::potential_query_instability)]
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index d13c71b78e4..88de43478b8 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1628,10 +1628,10 @@ struct ParamTag {
 
 impl_tag! {
     impl Tag for ParamTag;
-    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } <=> 0,
-    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::NotConst } <=> 1,
-    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const    } <=> 2,
-    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::Const    } <=> 3,
+    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
+    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::NotConst },
+    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const    },
+    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::Const    },
 }
 
 impl<'tcx> fmt::Debug for ParamEnv<'tcx> {