]> git.proxmox.com Git - rustc.git/blob - src/librustc/macros.rs
New upstream version 1.26.0+dfsg1
[rustc.git] / src / librustc / macros.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // ignore-tidy-linelength
12
13 macro_rules! enum_from_u32 {
14 ($(#[$attr:meta])* pub enum $name:ident {
15 $($variant:ident = $e:expr,)*
16 }) => {
17 $(#[$attr])*
18 pub enum $name {
19 $($variant = $e),*
20 }
21
22 impl $name {
23 pub fn from_u32(u: u32) -> Option<$name> {
24 $(if u == $name::$variant as u32 {
25 return Some($name::$variant)
26 })*
27 None
28 }
29 }
30 };
31 ($(#[$attr:meta])* pub enum $name:ident {
32 $($variant:ident,)*
33 }) => {
34 $(#[$attr])*
35 pub enum $name {
36 $($variant,)*
37 }
38
39 impl $name {
40 pub fn from_u32(u: u32) -> Option<$name> {
41 $(if u == $name::$variant as u32 {
42 return Some($name::$variant)
43 })*
44 None
45 }
46 }
47 }
48 }
49
50 #[macro_export]
51 macro_rules! bug {
52 () => ( bug!("impossible case reached") );
53 ($($message:tt)*) => ({
54 $crate::session::bug_fmt(file!(), line!(), format_args!($($message)*))
55 })
56 }
57
58 #[macro_export]
59 macro_rules! span_bug {
60 ($span:expr, $($message:tt)*) => ({
61 $crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*))
62 })
63 }
64
65 #[macro_export]
66 macro_rules! __impl_stable_hash_field {
67 (DECL IGNORED) => (_);
68 (DECL $name:ident) => (ref $name);
69 (USE IGNORED $ctx:expr, $hasher:expr) => ({});
70 (USE $name:ident, $ctx:expr, $hasher:expr) => ($name.hash_stable($ctx, $hasher));
71 }
72
73 #[macro_export]
74 macro_rules! impl_stable_hash_for {
75 (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* $(,)* }) => {
76 impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $enum_name {
77 #[inline]
78 fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
79 __ctx: &mut $crate::ich::StableHashingContext<'a>,
80 __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
81 use $enum_name::*;
82 ::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
83
84 match *self {
85 $(
86 $variant $( ( $( __impl_stable_hash_field!(DECL $arg) ),* ) )* => {
87 $($( __impl_stable_hash_field!(USE $arg, __ctx, __hasher) );*)*
88 }
89 )*
90 }
91 }
92 }
93 };
94 (struct $struct_name:path { $($field:ident),* }) => {
95 impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name {
96 #[inline]
97 fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
98 __ctx: &mut $crate::ich::StableHashingContext<'a>,
99 __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
100 let $struct_name {
101 $(ref $field),*
102 } = *self;
103
104 $( $field.hash_stable(__ctx, __hasher));*
105 }
106 }
107 };
108 (tuple_struct $struct_name:path { $($field:ident),* }) => {
109 impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name {
110 #[inline]
111 fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
112 __ctx: &mut $crate::ich::StableHashingContext<'a>,
113 __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
114 let $struct_name (
115 $(ref $field),*
116 ) = *self;
117
118 $( $field.hash_stable(__ctx, __hasher));*
119 }
120 }
121 };
122
123 (impl<$tcx:lifetime $(, $T:ident)*> for struct $struct_name:path {
124 $($field:ident),* $(,)*
125 }) => {
126 impl<'a, $tcx, $($T,)*> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name
127 where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),*
128 {
129 #[inline]
130 fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
131 __ctx: &mut $crate::ich::StableHashingContext<'a>,
132 __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
133 let $struct_name {
134 $(ref $field),*
135 } = *self;
136
137 $( $field.hash_stable(__ctx, __hasher));*
138 }
139 }
140 };
141 }
142
143 #[macro_export]
144 macro_rules! impl_stable_hash_for_spanned {
145 ($T:path) => (
146
147 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ::syntax::codemap::Spanned<$T>
148 {
149 #[inline]
150 fn hash_stable<W: StableHasherResult>(&self,
151 hcx: &mut StableHashingContext<'a>,
152 hasher: &mut StableHasher<W>) {
153 self.node.hash_stable(hcx, hasher);
154 self.span.hash_stable(hcx, hasher);
155 }
156 }
157 );
158 }
159
160 ///////////////////////////////////////////////////////////////////////////
161 // Lift and TypeFoldable macros
162 //
163 // When possible, use one of these (relatively) convenient macros to write
164 // the impls for you.
165
166 #[macro_export]
167 macro_rules! CloneLiftImpls {
168 (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
169 $(
170 impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
171 type Lifted = Self;
172 fn lift_to_tcx<'a, 'gcx>(&self, _: $crate::ty::TyCtxt<'a, 'gcx, $tcx>) -> Option<Self> {
173 Some(Clone::clone(self))
174 }
175 }
176 )+
177 };
178
179 ($($ty:ty,)+) => {
180 CloneLiftImpls! {
181 for <'tcx> {
182 $($ty,)+
183 }
184 }
185 };
186 }
187
188 /// Used for types that are `Copy` and which **do not care arena
189 /// allocated data** (i.e., don't need to be folded).
190 #[macro_export]
191 macro_rules! CloneTypeFoldableImpls {
192 (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
193 $(
194 impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
195 fn super_fold_with<'gcx: $tcx, F: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
196 &self,
197 _: &mut F
198 ) -> $ty {
199 Clone::clone(self)
200 }
201
202 fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
203 &self,
204 _: &mut F)
205 -> bool
206 {
207 false
208 }
209 }
210 )+
211 };
212
213 ($($ty:ty,)+) => {
214 CloneTypeFoldableImpls! {
215 for <'tcx> {
216 $($ty,)+
217 }
218 }
219 };
220 }
221
222 #[macro_export]
223 macro_rules! CloneTypeFoldableAndLiftImpls {
224 ($($t:tt)*) => {
225 CloneTypeFoldableImpls! { $($t)* }
226 CloneLiftImpls! { $($t)* }
227 }
228 }
229
230 #[macro_export]
231 macro_rules! BraceStructLiftImpl {
232 (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path {
233 type Lifted = $lifted:ty;
234 $($field:ident),* $(,)*
235 } $(where $($wc:tt)*)*) => {
236 impl<$($p),*> $crate::ty::Lift<$tcx> for $s
237 $(where $($wc)*)*
238 {
239 type Lifted = $lifted;
240
241 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> {
242 $(let $field = tcx.lift(&self.$field)?;)*
243 Some(Self::Lifted { $($field),* })
244 }
245 }
246 };
247 }
248
249 #[macro_export]
250 macro_rules! EnumLiftImpl {
251 (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path {
252 type Lifted = $lifted:ty;
253 $(
254 ($variant:path) ( $( $variant_arg:ident),* )
255 ),*
256 $(,)*
257 } $(where $($wc:tt)*)*) => {
258 impl<$($p),*> $crate::ty::Lift<$tcx> for $s
259 $(where $($wc)*)*
260 {
261 type Lifted = $lifted;
262
263 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> {
264 match self {
265 $($variant ( $($variant_arg),* ) => {
266 Some($variant ( $(tcx.lift($variant_arg)?),* ))
267 })*
268 }
269 }
270 }
271 };
272 }
273
274 #[macro_export]
275 macro_rules! BraceStructTypeFoldableImpl {
276 (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
277 $($field:ident),* $(,)*
278 } $(where $($wc:tt)*)*) => {
279 impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
280 $(where $($wc)*)*
281 {
282 fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
283 &self,
284 folder: &mut V,
285 ) -> Self {
286 let $s { $($field,)* } = self;
287 $s { $($field: $crate::ty::fold::TypeFoldable::fold_with($field, folder),)* }
288 }
289
290 fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
291 &self,
292 visitor: &mut V,
293 ) -> bool {
294 let $s { $($field,)* } = self;
295 false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))*
296 }
297 }
298 };
299 }
300
301 #[macro_export]
302 macro_rules! TupleStructTypeFoldableImpl {
303 (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
304 $($field:ident),* $(,)*
305 } $(where $($wc:tt)*)*) => {
306 impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
307 $(where $($wc)*)*
308 {
309 fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
310 &self,
311 folder: &mut V,
312 ) -> Self {
313 let $s($($field,)*)= self;
314 $s($($crate::ty::fold::TypeFoldable::fold_with($field, folder),)*)
315 }
316
317 fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
318 &self,
319 visitor: &mut V,
320 ) -> bool {
321 let $s($($field,)*) = self;
322 false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))*
323 }
324 }
325 };
326 }
327
328 #[macro_export]
329 macro_rules! EnumTypeFoldableImpl {
330 (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
331 $($variants:tt)*
332 } $(where $($wc:tt)*)*) => {
333 impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
334 $(where $($wc)*)*
335 {
336 fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
337 &self,
338 folder: &mut V,
339 ) -> Self {
340 EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output())
341 }
342
343 fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
344 &self,
345 visitor: &mut V,
346 ) -> bool {
347 EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
348 }
349 }
350 };
351
352 (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
353 match $this {
354 $($output)*
355 }
356 };
357
358 (@FoldVariants($this:expr, $folder:expr)
359 input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
360 output( $($output:tt)*) ) => {
361 EnumTypeFoldableImpl!(
362 @FoldVariants($this, $folder)
363 input($($input)*)
364 output(
365 $variant ( $($variant_arg),* ) => {
366 $variant (
367 $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),*
368 )
369 }
370 $($output)*
371 )
372 )
373 };
374
375 (@FoldVariants($this:expr, $folder:expr)
376 input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*)
377 output( $($output:tt)*) ) => {
378 EnumTypeFoldableImpl!(
379 @FoldVariants($this, $folder)
380 input($($input)*)
381 output(
382 $variant { $($variant_arg),* } => {
383 $variant {
384 $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
385 $variant_arg, $folder
386 )),* }
387 }
388 $($output)*
389 )
390 )
391 };
392
393 (@FoldVariants($this:expr, $folder:expr)
394 input( ($variant:path), $($input:tt)*)
395 output( $($output:tt)*) ) => {
396 EnumTypeFoldableImpl!(
397 @FoldVariants($this, $folder)
398 input($($input)*)
399 output(
400 $variant => { $variant }
401 $($output)*
402 )
403 )
404 };
405
406 (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
407 match $this {
408 $($output)*
409 }
410 };
411
412 (@VisitVariants($this:expr, $visitor:expr)
413 input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
414 output( $($output:tt)*) ) => {
415 EnumTypeFoldableImpl!(
416 @VisitVariants($this, $visitor)
417 input($($input)*)
418 output(
419 $variant ( $($variant_arg),* ) => {
420 false $(|| $crate::ty::fold::TypeFoldable::visit_with(
421 $variant_arg, $visitor
422 ))*
423 }
424 $($output)*
425 )
426 )
427 };
428
429 (@VisitVariants($this:expr, $visitor:expr)
430 input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*)
431 output( $($output:tt)*) ) => {
432 EnumTypeFoldableImpl!(
433 @VisitVariants($this, $visitor)
434 input($($input)*)
435 output(
436 $variant { $($variant_arg),* } => {
437 false $(|| $crate::ty::fold::TypeFoldable::visit_with(
438 $variant_arg, $visitor
439 ))*
440 }
441 $($output)*
442 )
443 )
444 };
445
446 (@VisitVariants($this:expr, $visitor:expr)
447 input( ($variant:path), $($input:tt)*)
448 output( $($output:tt)*) ) => {
449 EnumTypeFoldableImpl!(
450 @VisitVariants($this, $visitor)
451 input($($input)*)
452 output(
453 $variant => { false }
454 $($output)*
455 )
456 )
457 };
458 }
459