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