]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/macros.rs
Auto merge of #104875 - chenyukang:yukang/fix-104867-inc, r=estebank
[rust.git] / compiler / rustc_middle / src / macros.rs
1 #[macro_export]
2 macro_rules! bug {
3     () => ( $crate::bug!("impossible case reached") );
4     ($msg:expr) => ({ $crate::util::bug::bug_fmt(::std::format_args!($msg)) });
5     ($msg:expr,) => ({ $crate::bug!($msg) });
6     ($fmt:expr, $($arg:tt)+) => ({
7         $crate::util::bug::bug_fmt(::std::format_args!($fmt, $($arg)+))
8     });
9 }
10
11 #[macro_export]
12 macro_rules! span_bug {
13     ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
14     ($span:expr, $msg:expr,) => ({ $crate::span_bug!($span, $msg) });
15     ($span:expr, $fmt:expr, $($arg:tt)+) => ({
16         $crate::util::bug::span_bug_fmt($span, ::std::format_args!($fmt, $($arg)+))
17     });
18 }
19
20 ///////////////////////////////////////////////////////////////////////////
21 // Lift and TypeFoldable/TypeVisitable macros
22 //
23 // When possible, use one of these (relatively) convenient macros to write
24 // the impls for you.
25
26 #[macro_export]
27 macro_rules! CloneLiftImpls {
28     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
29         $(
30             impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
31                 type Lifted = Self;
32                 fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option<Self> {
33                     Some(self)
34                 }
35             }
36         )+
37     };
38
39     ($($ty:ty,)+) => {
40         CloneLiftImpls! {
41             for <'tcx> {
42                 $($ty,)+
43             }
44         }
45     };
46 }
47
48 /// Used for types that are `Copy` and which **do not care arena
49 /// allocated data** (i.e., don't need to be folded).
50 #[macro_export]
51 macro_rules! TrivialTypeTraversalImpls {
52     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
53         $(
54             impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
55                 fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
56                     self,
57                     _: &mut F,
58                 ) -> ::std::result::Result<Self, F::Error> {
59                     Ok(self)
60                 }
61
62                 #[inline]
63                 fn fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
64                     self,
65                     _: &mut F,
66                 ) -> Self {
67                     self
68                 }
69             }
70
71             impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty {
72                 #[inline]
73                 fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>(
74                     &self,
75                     _: &mut F)
76                     -> ::std::ops::ControlFlow<F::BreakTy>
77                 {
78                     ::std::ops::ControlFlow::CONTINUE
79                 }
80             }
81         )+
82     };
83
84     ($($ty:ty,)+) => {
85         TrivialTypeTraversalImpls! {
86             for <'tcx> {
87                 $($ty,)+
88             }
89         }
90     };
91 }
92
93 #[macro_export]
94 macro_rules! TrivialTypeTraversalAndLiftImpls {
95     ($($t:tt)*) => {
96         TrivialTypeTraversalImpls! { $($t)* }
97         CloneLiftImpls! { $($t)* }
98     }
99 }
100
101 #[macro_export]
102 macro_rules! EnumTypeTraversalImpl {
103     (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
104         $($variants:tt)*
105     } $(where $($wc:tt)*)*) => {
106         impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
107             $(where $($wc)*)*
108         {
109             fn try_fold_with<V: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
110                 self,
111                 folder: &mut V,
112             ) -> ::std::result::Result<Self, V::Error> {
113                 EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
114             }
115         }
116     };
117
118     (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
119         $($variants:tt)*
120     } $(where $($wc:tt)*)*) => {
121         impl<$($p),*> $crate::ty::visit::TypeVisitable<$tcx> for $s
122             $(where $($wc)*)*
123         {
124             fn visit_with<V: $crate::ty::visit::TypeVisitor<$tcx>>(
125                 &self,
126                 visitor: &mut V,
127             ) -> ::std::ops::ControlFlow<V::BreakTy> {
128                 EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
129             }
130         }
131     };
132
133     (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
134         Ok(match $this {
135             $($output)*
136         })
137     };
138
139     (@FoldVariants($this:expr, $folder:expr)
140      input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
141      output( $($output:tt)*) ) => {
142         EnumTypeTraversalImpl!(
143             @FoldVariants($this, $folder)
144                 input($($input)*)
145                 output(
146                     $variant ( $($variant_arg),* ) => {
147                         $variant (
148                             $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
149                         )
150                     }
151                     $($output)*
152                 )
153         )
154     };
155
156     (@FoldVariants($this:expr, $folder:expr)
157      input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
158      output( $($output:tt)*) ) => {
159         EnumTypeTraversalImpl!(
160             @FoldVariants($this, $folder)
161                 input($($input)*)
162                 output(
163                     $variant { $($variant_arg),* } => {
164                         $variant {
165                             $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
166                                 $variant_arg, $folder
167                             )?),* }
168                     }
169                     $($output)*
170                 )
171         )
172     };
173
174     (@FoldVariants($this:expr, $folder:expr)
175      input( ($variant:path), $($input:tt)*)
176      output( $($output:tt)*) ) => {
177         EnumTypeTraversalImpl!(
178             @FoldVariants($this, $folder)
179                 input($($input)*)
180                 output(
181                     $variant => { $variant }
182                     $($output)*
183                 )
184         )
185     };
186
187     (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
188         match $this {
189             $($output)*
190         }
191     };
192
193     (@VisitVariants($this:expr, $visitor:expr)
194      input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
195      output( $($output:tt)*) ) => {
196         EnumTypeTraversalImpl!(
197             @VisitVariants($this, $visitor)
198                 input($($input)*)
199                 output(
200                     $variant ( $($variant_arg),* ) => {
201                         $($crate::ty::visit::TypeVisitable::visit_with(
202                             $variant_arg, $visitor
203                         )?;)*
204                         ::std::ops::ControlFlow::CONTINUE
205                     }
206                     $($output)*
207                 )
208         )
209     };
210
211     (@VisitVariants($this:expr, $visitor:expr)
212      input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
213      output( $($output:tt)*) ) => {
214         EnumTypeTraversalImpl!(
215             @VisitVariants($this, $visitor)
216                 input($($input)*)
217                 output(
218                     $variant { $($variant_arg),* } => {
219                         $($crate::ty::visit::TypeVisitable::visit_with(
220                             $variant_arg, $visitor
221                         )?;)*
222                         ::std::ops::ControlFlow::CONTINUE
223                     }
224                     $($output)*
225                 )
226         )
227     };
228
229     (@VisitVariants($this:expr, $visitor:expr)
230      input( ($variant:path), $($input:tt)*)
231      output( $($output:tt)*) ) => {
232         EnumTypeTraversalImpl!(
233             @VisitVariants($this, $visitor)
234                 input($($input)*)
235                 output(
236                     $variant => { ::std::ops::ControlFlow::CONTINUE }
237                     $($output)*
238                 )
239         )
240     };
241 }