]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/macros.rs
emit `ConstEquate` in `TypeRelating<D>`
[rust.git] / compiler / rustc_middle / src / macros.rs
1 /// A macro for triggering an ICE.
2 /// Calling `bug` instead of panicking will result in a nicer error message and should
3 /// therefore be prefered over `panic`/`unreachable` or others.
4 ///
5 /// If you have a span available, you should use [`span_bug`] instead.
6 ///
7 /// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
8 ///
9 /// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
10 /// [`span_bug`]: crate::span_bug
11 #[macro_export]
12 macro_rules! bug {
13     () => ( $crate::bug!("impossible case reached") );
14     ($msg:expr) => ({ $crate::util::bug::bug_fmt(::std::format_args!($msg)) });
15     ($msg:expr,) => ({ $crate::bug!($msg) });
16     ($fmt:expr, $($arg:tt)+) => ({
17         $crate::util::bug::bug_fmt(::std::format_args!($fmt, $($arg)+))
18     });
19 }
20
21 /// A macro for triggering an ICE with a span.
22 /// Calling `span_bug!` instead of panicking will result in a nicer error message and point
23 /// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
24 /// ICEs.
25 ///
26 /// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
27 ///
28 /// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
29 #[macro_export]
30 macro_rules! span_bug {
31     ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
32     ($span:expr, $msg:expr,) => ({ $crate::span_bug!($span, $msg) });
33     ($span:expr, $fmt:expr, $($arg:tt)+) => ({
34         $crate::util::bug::span_bug_fmt($span, ::std::format_args!($fmt, $($arg)+))
35     });
36 }
37
38 ///////////////////////////////////////////////////////////////////////////
39 // Lift and TypeFoldable/TypeVisitable macros
40 //
41 // When possible, use one of these (relatively) convenient macros to write
42 // the impls for you.
43
44 #[macro_export]
45 macro_rules! CloneLiftImpls {
46     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
47         $(
48             impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
49                 type Lifted = Self;
50                 fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option<Self> {
51                     Some(self)
52                 }
53             }
54         )+
55     };
56
57     ($($ty:ty,)+) => {
58         CloneLiftImpls! {
59             for <'tcx> {
60                 $($ty,)+
61             }
62         }
63     };
64 }
65
66 /// Used for types that are `Copy` and which **do not care arena
67 /// allocated data** (i.e., don't need to be folded).
68 #[macro_export]
69 macro_rules! TrivialTypeTraversalImpls {
70     (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
71         $(
72             impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
73                 fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
74                     self,
75                     _: &mut F,
76                 ) -> ::std::result::Result<Self, F::Error> {
77                     Ok(self)
78                 }
79
80                 #[inline]
81                 fn fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
82                     self,
83                     _: &mut F,
84                 ) -> Self {
85                     self
86                 }
87             }
88
89             impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty {
90                 #[inline]
91                 fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>(
92                     &self,
93                     _: &mut F)
94                     -> ::std::ops::ControlFlow<F::BreakTy>
95                 {
96                     ::std::ops::ControlFlow::Continue(())
97                 }
98             }
99         )+
100     };
101
102     ($($ty:ty,)+) => {
103         TrivialTypeTraversalImpls! {
104             for <'tcx> {
105                 $($ty,)+
106             }
107         }
108     };
109 }
110
111 #[macro_export]
112 macro_rules! TrivialTypeTraversalAndLiftImpls {
113     ($($t:tt)*) => {
114         TrivialTypeTraversalImpls! { $($t)* }
115         CloneLiftImpls! { $($t)* }
116     }
117 }
118
119 #[macro_export]
120 macro_rules! EnumTypeTraversalImpl {
121     (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
122         $($variants:tt)*
123     } $(where $($wc:tt)*)*) => {
124         impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
125             $(where $($wc)*)*
126         {
127             fn try_fold_with<V: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
128                 self,
129                 folder: &mut V,
130             ) -> ::std::result::Result<Self, V::Error> {
131                 EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
132             }
133         }
134     };
135
136     (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
137         $($variants:tt)*
138     } $(where $($wc:tt)*)*) => {
139         impl<$($p),*> $crate::ty::visit::TypeVisitable<$tcx> for $s
140             $(where $($wc)*)*
141         {
142             fn visit_with<V: $crate::ty::visit::TypeVisitor<$tcx>>(
143                 &self,
144                 visitor: &mut V,
145             ) -> ::std::ops::ControlFlow<V::BreakTy> {
146                 EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
147             }
148         }
149     };
150
151     (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
152         Ok(match $this {
153             $($output)*
154         })
155     };
156
157     (@FoldVariants($this:expr, $folder:expr)
158      input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
159      output( $($output:tt)*) ) => {
160         EnumTypeTraversalImpl!(
161             @FoldVariants($this, $folder)
162                 input($($input)*)
163                 output(
164                     $variant ( $($variant_arg),* ) => {
165                         $variant (
166                             $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
167                         )
168                     }
169                     $($output)*
170                 )
171         )
172     };
173
174     (@FoldVariants($this:expr, $folder:expr)
175      input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
176      output( $($output:tt)*) ) => {
177         EnumTypeTraversalImpl!(
178             @FoldVariants($this, $folder)
179                 input($($input)*)
180                 output(
181                     $variant { $($variant_arg),* } => {
182                         $variant {
183                             $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
184                                 $variant_arg, $folder
185                             )?),* }
186                     }
187                     $($output)*
188                 )
189         )
190     };
191
192     (@FoldVariants($this:expr, $folder:expr)
193      input( ($variant:path), $($input:tt)*)
194      output( $($output:tt)*) ) => {
195         EnumTypeTraversalImpl!(
196             @FoldVariants($this, $folder)
197                 input($($input)*)
198                 output(
199                     $variant => { $variant }
200                     $($output)*
201                 )
202         )
203     };
204
205     (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
206         match $this {
207             $($output)*
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) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
231      output( $($output:tt)*) ) => {
232         EnumTypeTraversalImpl!(
233             @VisitVariants($this, $visitor)
234                 input($($input)*)
235                 output(
236                     $variant { $($variant_arg),* } => {
237                         $($crate::ty::visit::TypeVisitable::visit_with(
238                             $variant_arg, $visitor
239                         )?;)*
240                         ::std::ops::ControlFlow::Continue(())
241                     }
242                     $($output)*
243                 )
244         )
245     };
246
247     (@VisitVariants($this:expr, $visitor:expr)
248      input( ($variant:path), $($input:tt)*)
249      output( $($output:tt)*) ) => {
250         EnumTypeTraversalImpl!(
251             @VisitVariants($this, $visitor)
252                 input($($input)*)
253                 output(
254                     $variant => { ::std::ops::ControlFlow::Continue(()) }
255                     $($output)*
256                 )
257         )
258     };
259 }