]> git.lizzy.rs Git - rust.git/blob - src/librustc/macros.rs
Don't default on std crate when manipulating browser history
[rust.git] / src / librustc / macros.rs
1 // ignore-tidy-linelength
2
3 macro_rules! enum_from_u32 {
4     ($(#[$attr:meta])* pub enum $name:ident {
5         $($variant:ident = $e:expr,)*
6     }) => {
7         $(#[$attr])*
8         pub enum $name {
9             $($variant = $e),*
10         }
11
12         impl $name {
13             pub fn from_u32(u: u32) -> Option<$name> {
14                 $(if u == $name::$variant as u32 {
15                     return Some($name::$variant)
16                 })*
17                 None
18             }
19         }
20     };
21     ($(#[$attr:meta])* pub enum $name:ident {
22         $($variant:ident,)*
23     }) => {
24         $(#[$attr])*
25         pub enum $name {
26             $($variant,)*
27         }
28
29         impl $name {
30             pub fn from_u32(u: u32) -> Option<$name> {
31                 $(if u == $name::$variant as u32 {
32                     return Some($name::$variant)
33                 })*
34                 None
35             }
36         }
37     }
38 }
39
40 #[macro_export]
41 macro_rules! bug {
42     () => ( bug!("impossible case reached") );
43     ($($message:tt)*) => ({
44         $crate::util::bug::bug_fmt(file!(), line!(), format_args!($($message)*))
45     })
46 }
47
48 #[macro_export]
49 macro_rules! span_bug {
50     ($span:expr, $($message:tt)*) => ({
51         $crate::util::bug::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*))
52     })
53 }
54
55 #[macro_export]
56 macro_rules! __impl_stable_hash_field {
57     ($field:ident, $ctx:expr, $hasher:expr) => ($field.hash_stable($ctx, $hasher));
58     ($field:ident, $ctx:expr, $hasher:expr, _) => ({ let _ = $field; });
59     ($field:ident, $ctx:expr, $hasher:expr, $delegate:expr) => ($delegate.hash_stable($ctx, $hasher));
60 }
61
62 #[macro_export]
63 macro_rules! impl_stable_hash_for {
64     // Enums
65     // FIXME(mark-i-m): Some of these should be `?` rather than `*`. See the git blame and change
66     // them back when `?` is supported again.
67     (enum $enum_name:path {
68         $( $variant:ident
69            // this incorrectly allows specifying both tuple-like and struct-like fields, as in `Variant(a,b){c,d}`,
70            // when it should be only one or the other
71            $( ( $($field:ident $(-> $delegate:tt)*),* ) )*
72            $( { $($named_field:ident $(-> $named_delegate:tt)*),* } )*
73         ),* $(,)*
74     }) => {
75         impl_stable_hash_for!(
76             impl<> for enum $enum_name [ $enum_name ] { $( $variant
77                 $( ( $($field $(-> $delegate)*),* ) )*
78                 $( { $($named_field $(-> $named_delegate)*),* } )*
79             ),* }
80         );
81     };
82     // We want to use the enum name both in the `impl ... for $enum_name` as well as for
83     // importing all the variants. Unfortunately it seems we have to take the name
84     // twice for this purpose
85     (impl<$($lt:lifetime $(: $lt_bound:lifetime)* ),* $(,)* $($T:ident),* $(,)*>
86         for enum $enum_name:path
87         [ $enum_path:path ]
88     {
89         $( $variant:ident
90            // this incorrectly allows specifying both tuple-like and struct-like fields, as in `Variant(a,b){c,d}`,
91            // when it should be only one or the other
92            $( ( $($field:ident $(-> $delegate:tt)*),* ) )*
93            $( { $($named_field:ident $(-> $named_delegate:tt)*),* } )*
94         ),* $(,)*
95     }) => {
96         impl<'a, $($lt $(: $lt_bound)*,)* $($T,)*>
97             ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>
98             for $enum_name
99             where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),*
100         {
101             #[inline]
102             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
103                                                   __ctx: &mut $crate::ich::StableHashingContext<'a>,
104                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
105                 use $enum_path::*;
106                 ::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
107
108                 match *self {
109                     $(
110                         $variant $( ( $(ref $field),* ) )* $( { $(ref $named_field),* } )* => {
111                             $($( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*)*
112                             $($( __impl_stable_hash_field!($named_field, __ctx, __hasher $(, $named_delegate)*) );*)*
113                         }
114                     )*
115                 }
116             }
117         }
118     };
119     // Structs
120     // FIXME(mark-i-m): same here.
121     (struct $struct_name:path { $($field:ident $(-> $delegate:tt)*),*  $(,)* }) => {
122         impl_stable_hash_for!(
123             impl<'tcx> for struct $struct_name { $($field $(-> $delegate)*),* }
124         );
125     };
126     (impl<$($lt:lifetime $(: $lt_bound:lifetime)* ),* $(,)* $($T:ident),* $(,)*> for struct $struct_name:path {
127         $($field:ident $(-> $delegate:tt)*),* $(,)*
128     }) => {
129         impl<'a, $($lt $(: $lt_bound)*,)* $($T,)*>
130             ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name
131             where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),*
132         {
133             #[inline]
134             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
135                                                   __ctx: &mut $crate::ich::StableHashingContext<'a>,
136                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
137                 let $struct_name {
138                     $(ref $field),*
139                 } = *self;
140
141                 $( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*
142             }
143         }
144     };
145     // Tuple structs
146     // We cannot use normale parentheses here, the parser won't allow it
147     // FIXME(mark-i-m): same here.
148     (tuple_struct $struct_name:path { $($field:ident $(-> $delegate:tt)*),*  $(,)* }) => {
149         impl_stable_hash_for!(
150             impl<'tcx> for tuple_struct $struct_name { $($field $(-> $delegate)*),* }
151         );
152     };
153     (impl<$($lt:lifetime $(: $lt_bound:lifetime)* ),* $(,)* $($T:ident),* $(,)*>
154      for tuple_struct $struct_name:path { $($field:ident $(-> $delegate:tt)*),*  $(,)* }) => {
155         impl<'a, $($lt $(: $lt_bound)*,)* $($T,)*>
156             ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name
157             where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),*
158         {
159             #[inline]
160             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
161                                                   __ctx: &mut $crate::ich::StableHashingContext<'a>,
162                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
163                 let $struct_name (
164                     $(ref $field),*
165                 ) = *self;
166
167                 $( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*
168             }
169         }
170     };
171 }
172
173 #[macro_export]
174 macro_rules! impl_stable_hash_for_spanned {
175     ($T:path) => (
176
177         impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ::syntax::source_map::Spanned<$T>
178         {
179             #[inline]
180             fn hash_stable<W: StableHasherResult>(&self,
181                                                   hcx: &mut StableHashingContext<'a>,
182                                                   hasher: &mut StableHasher<W>) {
183                 self.node.hash_stable(hcx, hasher);
184                 self.span.hash_stable(hcx, hasher);
185             }
186         }
187     );
188 }
189
190 ///////////////////////////////////////////////////////////////////////////
191 // Lift and TypeFoldable macros
192 //
193 // When possible, use one of these (relatively) convenient macros to write
194 // the impls for you.
195
196 #[macro_export]
197 macro_rules! CloneLiftImpls {
198     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
199         $(
200             impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
201                 type Lifted = Self;
202                 fn lift_to_tcx<'a, 'gcx>(&self, _: $crate::ty::TyCtxt<'a, 'gcx, $tcx>) -> Option<Self> {
203                     Some(Clone::clone(self))
204                 }
205             }
206         )+
207     };
208
209     ($($ty:ty,)+) => {
210         CloneLiftImpls! {
211             for <'tcx> {
212                 $($ty,)+
213             }
214         }
215     };
216 }
217
218 /// Used for types that are `Copy` and which **do not care arena
219 /// allocated data** (i.e., don't need to be folded).
220 #[macro_export]
221 macro_rules! CloneTypeFoldableImpls {
222     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
223         $(
224             impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
225                 fn super_fold_with<'gcx: $tcx, F: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
226                     &self,
227                     _: &mut F
228                 ) -> $ty {
229                     Clone::clone(self)
230                 }
231
232                 fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
233                     &self,
234                     _: &mut F)
235                     -> bool
236                 {
237                     false
238                 }
239             }
240         )+
241     };
242
243     ($($ty:ty,)+) => {
244         CloneTypeFoldableImpls! {
245             for <'tcx> {
246                 $($ty,)+
247             }
248         }
249     };
250 }
251
252 #[macro_export]
253 macro_rules! CloneTypeFoldableAndLiftImpls {
254     ($($t:tt)*) => {
255         CloneTypeFoldableImpls! { $($t)* }
256         CloneLiftImpls! { $($t)* }
257     }
258 }
259
260 #[macro_export]
261 macro_rules! BraceStructLiftImpl {
262     (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path {
263         type Lifted = $lifted:ty;
264         $($field:ident),* $(,)*
265     } $(where $($wc:tt)*)*) => {
266         impl<$($p),*> $crate::ty::Lift<$tcx> for $s
267             $(where $($wc)*)*
268         {
269             type Lifted = $lifted;
270
271             fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> {
272                 $(let $field = tcx.lift(&self.$field)?;)*
273                 Some(Self::Lifted { $($field),* })
274             }
275         }
276     };
277 }
278
279 #[macro_export]
280 macro_rules! EnumLiftImpl {
281     (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path {
282         type Lifted = $lifted:ty;
283         $($variants:tt)*
284     } $(where $($wc:tt)*)*) => {
285         impl<$($p),*> $crate::ty::Lift<$tcx> for $s
286             $(where $($wc)*)*
287         {
288             type Lifted = $lifted;
289
290             fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> {
291                 EnumLiftImpl!(@Variants(self, tcx) input($($variants)*) output())
292             }
293         }
294     };
295
296     (@Variants($this:expr, $tcx:expr) input() output($($output:tt)*)) => {
297         match $this {
298             $($output)*
299         }
300     };
301
302     (@Variants($this:expr, $tcx:expr)
303      input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
304      output( $($output:tt)*) ) => {
305         EnumLiftImpl!(
306             @Variants($this, $tcx)
307                 input($($input)*)
308                 output(
309                     $variant ( $($variant_arg),* ) => {
310                         Some($variant ( $($tcx.lift($variant_arg)?),* ))
311                     }
312                     $($output)*
313                 )
314         )
315     };
316
317     (@Variants($this:expr, $tcx:expr)
318      input( ($variant:path), $($input:tt)*)
319      output( $($output:tt)*) ) => {
320         EnumLiftImpl!(
321             @Variants($this, $tcx)
322                 input($($input)*)
323                 output(
324                     $variant => { Some($variant) }
325                     $($output)*
326                 )
327         )
328     };
329 }
330
331 #[macro_export]
332 macro_rules! BraceStructTypeFoldableImpl {
333     (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
334         $($field:ident),* $(,)*
335     } $(where $($wc:tt)*)*) => {
336         impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
337             $(where $($wc)*)*
338         {
339             fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
340                 &self,
341                 folder: &mut V,
342             ) -> Self {
343                 let $s { $($field,)* } = self;
344                 $s { $($field: $crate::ty::fold::TypeFoldable::fold_with($field, folder),)* }
345             }
346
347             fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
348                 &self,
349                 visitor: &mut V,
350             ) -> bool {
351                 let $s { $($field,)* } = self;
352                 false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))*
353             }
354         }
355     };
356 }
357
358 #[macro_export]
359 macro_rules! TupleStructTypeFoldableImpl {
360     (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
361         $($field:ident),* $(,)*
362     } $(where $($wc:tt)*)*) => {
363         impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
364             $(where $($wc)*)*
365         {
366             fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
367                 &self,
368                 folder: &mut V,
369             ) -> Self {
370                 let $s($($field,)*)= self;
371                 $s($($crate::ty::fold::TypeFoldable::fold_with($field, folder),)*)
372             }
373
374             fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
375                 &self,
376                 visitor: &mut V,
377             ) -> bool {
378                 let $s($($field,)*) = self;
379                 false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))*
380             }
381         }
382     };
383 }
384
385 #[macro_export]
386 macro_rules! EnumTypeFoldableImpl {
387     (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
388         $($variants:tt)*
389     } $(where $($wc:tt)*)*) => {
390         impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
391             $(where $($wc)*)*
392         {
393             fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
394                 &self,
395                 folder: &mut V,
396             ) -> Self {
397                 EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output())
398             }
399
400             fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
401                 &self,
402                 visitor: &mut V,
403             ) -> bool {
404                 EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
405             }
406         }
407     };
408
409     (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
410         match $this {
411             $($output)*
412         }
413     };
414
415     (@FoldVariants($this:expr, $folder:expr)
416      input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
417      output( $($output:tt)*) ) => {
418         EnumTypeFoldableImpl!(
419             @FoldVariants($this, $folder)
420                 input($($input)*)
421                 output(
422                     $variant ( $($variant_arg),* ) => {
423                         $variant (
424                             $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),*
425                         )
426                     }
427                     $($output)*
428                 )
429         )
430     };
431
432     (@FoldVariants($this:expr, $folder:expr)
433      input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*)
434      output( $($output:tt)*) ) => {
435         EnumTypeFoldableImpl!(
436             @FoldVariants($this, $folder)
437                 input($($input)*)
438                 output(
439                     $variant { $($variant_arg),* } => {
440                         $variant {
441                             $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
442                                 $variant_arg, $folder
443                             )),* }
444                     }
445                     $($output)*
446                 )
447         )
448     };
449
450     (@FoldVariants($this:expr, $folder:expr)
451      input( ($variant:path), $($input:tt)*)
452      output( $($output:tt)*) ) => {
453         EnumTypeFoldableImpl!(
454             @FoldVariants($this, $folder)
455                 input($($input)*)
456                 output(
457                     $variant => { $variant }
458                     $($output)*
459                 )
460         )
461     };
462
463     (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
464         match $this {
465             $($output)*
466         }
467     };
468
469     (@VisitVariants($this:expr, $visitor:expr)
470      input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
471      output( $($output:tt)*) ) => {
472         EnumTypeFoldableImpl!(
473             @VisitVariants($this, $visitor)
474                 input($($input)*)
475                 output(
476                     $variant ( $($variant_arg),* ) => {
477                         false $(|| $crate::ty::fold::TypeFoldable::visit_with(
478                             $variant_arg, $visitor
479                         ))*
480                     }
481                     $($output)*
482                 )
483         )
484     };
485
486     (@VisitVariants($this:expr, $visitor:expr)
487      input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*)
488      output( $($output:tt)*) ) => {
489         EnumTypeFoldableImpl!(
490             @VisitVariants($this, $visitor)
491                 input($($input)*)
492                 output(
493                     $variant { $($variant_arg),* } => {
494                         false $(|| $crate::ty::fold::TypeFoldable::visit_with(
495                             $variant_arg, $visitor
496                         ))*
497                     }
498                     $($output)*
499                 )
500         )
501     };
502
503     (@VisitVariants($this:expr, $visitor:expr)
504      input( ($variant:path), $($input:tt)*)
505      output( $($output:tt)*) ) => {
506         EnumTypeFoldableImpl!(
507             @VisitVariants($this, $visitor)
508                 input($($input)*)
509                 output(
510                     $variant => { false }
511                     $($output)*
512                 )
513         )
514     };
515 }
516