|
81 | 81 | /// E::A,
|
82 | 82 | /// }
|
83 | 83 | /// ```
|
84 |
| -#[cfg(bootstrap)] |
85 |
| -#[macro_export] |
86 |
| -macro_rules! impl_tag { |
87 |
| - ( |
88 |
| - impl Tag for $Self:ty; |
89 |
| - $( |
90 |
| - $($path:ident)::* $( { $( $fields:tt )* })?, |
91 |
| - )* |
92 |
| - ) => { |
93 |
| - // Safety: |
94 |
| - // `bits_for_tags` is called on the same `${index()}`-es as |
95 |
| - // `into_usize` returns, thus `BITS` constant is correct. |
96 |
| - unsafe impl $crate::tagged_ptr::Tag for $Self { |
97 |
| - const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[ |
98 |
| - $( |
99 |
| - ${index()}, |
100 |
| - $( ${ignore(path)} )* |
101 |
| - )* |
102 |
| - ]); |
103 |
| - |
104 |
| - #[inline] |
105 |
| - fn into_usize(self) -> usize { |
106 |
| - // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc) |
107 |
| - // (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>) |
108 |
| - #[forbid(unreachable_patterns)] |
109 |
| - match self { |
110 |
| - // `match` is doing heavy lifting here, by requiring exhaustiveness |
111 |
| - $( |
112 |
| - $($path)::* $( { $( $fields )* } )? => ${index()}, |
113 |
| - )* |
114 |
| - } |
115 |
| - } |
116 |
| - |
117 |
| - #[inline] |
118 |
| - unsafe fn from_usize(tag: usize) -> Self { |
119 |
| - match tag { |
120 |
| - $( |
121 |
| - ${index()} => $($path)::* $( { $( $fields )* } )?, |
122 |
| - )* |
123 |
| - |
124 |
| - // Safety: |
125 |
| - // `into_usize` only returns `${index()}` of the same |
126 |
| - // repetition as we are filtering above, thus if this is |
127 |
| - // reached, the safety contract of this function was |
128 |
| - // already breached. |
129 |
| - _ => unsafe { |
130 |
| - debug_assert!( |
131 |
| - false, |
132 |
| - "invalid tag: {tag}\ |
133 |
| - (this is a bug in the caller of `from_usize`)" |
134 |
| - ); |
135 |
| - std::hint::unreachable_unchecked() |
136 |
| - }, |
137 |
| - } |
138 |
| - } |
139 |
| - |
140 |
| - } |
141 |
| - }; |
142 |
| -} |
143 |
| - |
144 |
| -/// Implements [`Tag`] for a given type. |
145 |
| -/// |
146 |
| -/// You can use `impl_tag` on structs and enums. |
147 |
| -/// You need to specify the type and all its possible values, |
148 |
| -/// which can only be paths with optional fields. |
149 |
| -/// |
150 |
| -/// [`Tag`]: crate::tagged_ptr::Tag |
151 |
| -/// |
152 |
| -/// # Examples |
153 |
| -/// |
154 |
| -/// Basic usage: |
155 |
| -/// |
156 |
| -/// ``` |
157 |
| -/// #![feature(macro_metavar_expr)] |
158 |
| -/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag}; |
159 |
| -/// |
160 |
| -/// #[derive(Copy, Clone, PartialEq, Debug)] |
161 |
| -/// enum SomeTag { |
162 |
| -/// A, |
163 |
| -/// B, |
164 |
| -/// X { v: bool }, |
165 |
| -/// Y(bool, bool), |
166 |
| -/// } |
167 |
| -/// |
168 |
| -/// impl_tag! { |
169 |
| -/// // The type for which the `Tag` will be implemented |
170 |
| -/// impl Tag for SomeTag; |
171 |
| -/// // You need to specify all possible tag values: |
172 |
| -/// SomeTag::A, // 0 |
173 |
| -/// SomeTag::B, // 1 |
174 |
| -/// // For variants with fields, you need to specify the fields: |
175 |
| -/// SomeTag::X { v: true }, // 2 |
176 |
| -/// SomeTag::X { v: false }, // 3 |
177 |
| -/// // For tuple variants use named syntax: |
178 |
| -/// SomeTag::Y { 0: true, 1: true }, // 4 |
179 |
| -/// SomeTag::Y { 0: false, 1: true }, // 5 |
180 |
| -/// SomeTag::Y { 0: true, 1: false }, // 6 |
181 |
| -/// SomeTag::Y { 0: false, 1: false }, // 7 |
182 |
| -/// } |
183 |
| -/// |
184 |
| -/// // Tag values are assigned in order: |
185 |
| -/// assert_eq!(SomeTag::A.into_usize(), 0); |
186 |
| -/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3); |
187 |
| -/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5); |
188 |
| -/// |
189 |
| -/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B); |
190 |
| -/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true }); |
191 |
| -/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false)); |
192 |
| -/// ``` |
193 |
| -/// |
194 |
| -/// Structs are supported: |
195 |
| -/// |
196 |
| -/// ``` |
197 |
| -/// #![feature(macro_metavar_expr)] |
198 |
| -/// # use rustc_data_structures::impl_tag; |
199 |
| -/// #[derive(Copy, Clone)] |
200 |
| -/// struct Flags { a: bool, b: bool } |
201 |
| -/// |
202 |
| -/// impl_tag! { |
203 |
| -/// impl Tag for Flags; |
204 |
| -/// Flags { a: true, b: true }, |
205 |
| -/// Flags { a: false, b: true }, |
206 |
| -/// Flags { a: true, b: false }, |
207 |
| -/// Flags { a: false, b: false }, |
208 |
| -/// } |
209 |
| -/// ``` |
210 |
| -/// |
211 |
| -/// Not specifying all values results in a compile error: |
212 |
| -/// |
213 |
| -/// ```compile_fail,E0004 |
214 |
| -/// #![feature(macro_metavar_expr)] |
215 |
| -/// # use rustc_data_structures::impl_tag; |
216 |
| -/// #[derive(Copy, Clone)] |
217 |
| -/// enum E { |
218 |
| -/// A, |
219 |
| -/// B, |
220 |
| -/// } |
221 |
| -/// |
222 |
| -/// impl_tag! { |
223 |
| -/// impl Tag for E; |
224 |
| -/// E::A, |
225 |
| -/// } |
226 |
| -/// ``` |
227 |
| -#[cfg(not(bootstrap))] |
228 | 84 | #[macro_export]
|
229 | 85 | macro_rules! impl_tag {
|
230 | 86 | (
|
|
0 commit comments