rustc_mir_build/thir/
print.rs

1use std::fmt::{self, Write};
2
3use rustc_middle::thir::*;
4use rustc_middle::ty;
5use rustc_middle::ty::TyCtxt;
6use rustc_span::def_id::LocalDefId;
7
8/// Create a THIR tree for debugging.
9pub fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
10    match super::cx::thir_body(tcx, owner_def) {
11        Ok((thir, expr)) => {
12            let thir = thir.steal();
13            let mut printer = ThirPrinter::new(&thir);
14            printer.print(expr);
15            printer.into_buffer()
16        }
17        Err(_) => "error".into(),
18    }
19}
20
21/// Create a list-like THIR representation for debugging.
22pub fn thir_flat(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
23    match super::cx::thir_body(tcx, owner_def) {
24        Ok((thir, _)) => format!("{:#?}", thir.steal()),
25        Err(_) => "error".into(),
26    }
27}
28
29struct ThirPrinter<'a, 'tcx> {
30    thir: &'a Thir<'tcx>,
31    fmt: String,
32}
33
34const INDENT: &str = "    ";
35
36macro_rules! print_indented {
37    ($writer:ident, $s:expr, $indent_lvl:expr) => {
38        $writer.indent($indent_lvl);
39        writeln!($writer, "{}", $s).expect("unable to write to ThirPrinter");
40    };
41}
42
43impl<'a, 'tcx> Write for ThirPrinter<'a, 'tcx> {
44    fn write_str(&mut self, s: &str) -> fmt::Result {
45        self.fmt.push_str(s);
46        Ok(())
47    }
48}
49
50impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
51    fn new(thir: &'a Thir<'tcx>) -> Self {
52        Self { thir, fmt: String::new() }
53    }
54
55    fn indent(&mut self, level: usize) {
56        for _ in 0..level {
57            self.fmt.push_str(INDENT);
58        }
59    }
60
61    fn print(&mut self, body_expr: ExprId) {
62        print_indented!(self, "params: [", 0);
63        for param in self.thir.params.iter() {
64            self.print_param(param, 1);
65        }
66        print_indented!(self, "]", 0);
67
68        print_indented!(self, "body:", 0);
69        self.print_expr(body_expr, 1);
70    }
71
72    fn into_buffer(self) -> String {
73        self.fmt
74    }
75
76    fn print_param(&mut self, param: &Param<'tcx>, depth_lvl: usize) {
77        let Param { pat, ty, ty_span, self_kind, hir_id } = param;
78
79        print_indented!(self, "Param {", depth_lvl);
80        print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
81        print_indented!(self, format!("ty_span: {:?}", ty_span), depth_lvl + 1);
82        print_indented!(self, format!("self_kind: {:?}", self_kind), depth_lvl + 1);
83        print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 1);
84
85        if let Some(pat) = pat {
86            print_indented!(self, "param: Some( ", depth_lvl + 1);
87            self.print_pat(pat, depth_lvl + 2);
88            print_indented!(self, ")", depth_lvl + 1);
89        } else {
90            print_indented!(self, "param: None", depth_lvl + 1);
91        }
92
93        print_indented!(self, "}", depth_lvl);
94    }
95
96    fn print_block(&mut self, block_id: BlockId, depth_lvl: usize) {
97        let Block { targeted_by_break, span, region_scope, stmts, expr, safety_mode } =
98            &self.thir.blocks[block_id];
99
100        print_indented!(self, "Block {", depth_lvl);
101        print_indented!(self, format!("targeted_by_break: {}", targeted_by_break), depth_lvl + 1);
102        print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
103        print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1);
104        print_indented!(self, format!("safety_mode: {:?}", safety_mode), depth_lvl + 1);
105
106        if stmts.len() > 0 {
107            print_indented!(self, "stmts: [", depth_lvl + 1);
108            for stmt in stmts.iter() {
109                self.print_stmt(*stmt, depth_lvl + 2);
110            }
111            print_indented!(self, "]", depth_lvl + 1);
112        } else {
113            print_indented!(self, "stmts: []", depth_lvl + 1);
114        }
115
116        if let Some(expr_id) = expr {
117            print_indented!(self, "expr:", depth_lvl + 1);
118            self.print_expr(*expr_id, depth_lvl + 2);
119        } else {
120            print_indented!(self, "expr: []", depth_lvl + 1);
121        }
122
123        print_indented!(self, "}", depth_lvl);
124    }
125
126    fn print_stmt(&mut self, stmt_id: StmtId, depth_lvl: usize) {
127        let Stmt { kind } = &self.thir.stmts[stmt_id];
128
129        print_indented!(self, "Stmt {", depth_lvl);
130
131        match kind {
132            StmtKind::Expr { scope, expr } => {
133                print_indented!(self, "kind: Expr {", depth_lvl + 1);
134                print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 2);
135                print_indented!(self, "expr:", depth_lvl + 2);
136                self.print_expr(*expr, depth_lvl + 3);
137                print_indented!(self, "}", depth_lvl + 1);
138            }
139            StmtKind::Let {
140                remainder_scope,
141                init_scope,
142                pattern,
143                initializer,
144                else_block,
145                lint_level,
146                span,
147            } => {
148                print_indented!(self, "kind: Let {", depth_lvl + 1);
149                print_indented!(
150                    self,
151                    format!("remainder_scope: {:?}", remainder_scope),
152                    depth_lvl + 2
153                );
154                print_indented!(self, format!("init_scope: {:?}", init_scope), depth_lvl + 2);
155
156                print_indented!(self, "pattern: ", depth_lvl + 2);
157                self.print_pat(pattern, depth_lvl + 3);
158                print_indented!(self, ",", depth_lvl + 2);
159
160                if let Some(init) = initializer {
161                    print_indented!(self, "initializer: Some(", depth_lvl + 2);
162                    self.print_expr(*init, depth_lvl + 3);
163                    print_indented!(self, ")", depth_lvl + 2);
164                } else {
165                    print_indented!(self, "initializer: None", depth_lvl + 2);
166                }
167
168                if let Some(else_block) = else_block {
169                    print_indented!(self, "else_block: Some(", depth_lvl + 2);
170                    self.print_block(*else_block, depth_lvl + 3);
171                    print_indented!(self, ")", depth_lvl + 2);
172                } else {
173                    print_indented!(self, "else_block: None", depth_lvl + 2);
174                }
175
176                print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 2);
177                print_indented!(self, format!("span: {:?}", span), depth_lvl + 2);
178                print_indented!(self, "}", depth_lvl + 1);
179            }
180        }
181
182        print_indented!(self, "}", depth_lvl);
183    }
184
185    fn print_expr(&mut self, expr: ExprId, depth_lvl: usize) {
186        let Expr { ty, temp_lifetime, span, kind } = &self.thir[expr];
187        print_indented!(self, "Expr {", depth_lvl);
188        print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
189        print_indented!(self, format!("temp_lifetime: {:?}", temp_lifetime), depth_lvl + 1);
190        print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
191        print_indented!(self, "kind: ", depth_lvl + 1);
192        self.print_expr_kind(kind, depth_lvl + 2);
193        print_indented!(self, "}", depth_lvl);
194    }
195
196    fn print_expr_kind(&mut self, expr_kind: &ExprKind<'tcx>, depth_lvl: usize) {
197        use rustc_middle::thir::ExprKind::*;
198
199        match expr_kind {
200            Scope { region_scope, value, lint_level } => {
201                print_indented!(self, "Scope {", depth_lvl);
202                print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1);
203                print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1);
204                print_indented!(self, "value:", depth_lvl + 1);
205                self.print_expr(*value, depth_lvl + 2);
206                print_indented!(self, "}", depth_lvl);
207            }
208            Box { value } => {
209                print_indented!(self, "Box {", depth_lvl);
210                self.print_expr(*value, depth_lvl + 1);
211                print_indented!(self, "}", depth_lvl);
212            }
213            If { if_then_scope, cond, then, else_opt } => {
214                print_indented!(self, "If {", depth_lvl);
215                print_indented!(self, format!("if_then_scope: {:?}", if_then_scope), depth_lvl + 1);
216                print_indented!(self, "cond:", depth_lvl + 1);
217                self.print_expr(*cond, depth_lvl + 2);
218                print_indented!(self, "then:", depth_lvl + 1);
219                self.print_expr(*then, depth_lvl + 2);
220
221                if let Some(else_expr) = else_opt {
222                    print_indented!(self, "else:", depth_lvl + 1);
223                    self.print_expr(*else_expr, depth_lvl + 2);
224                }
225
226                print_indented!(self, "}", depth_lvl);
227            }
228            Call { fun, args, ty, from_hir_call, fn_span } => {
229                print_indented!(self, "Call {", depth_lvl);
230                print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
231                print_indented!(self, format!("from_hir_call: {}", from_hir_call), depth_lvl + 1);
232                print_indented!(self, format!("fn_span: {:?}", fn_span), depth_lvl + 1);
233                print_indented!(self, "fun:", depth_lvl + 1);
234                self.print_expr(*fun, depth_lvl + 2);
235
236                if args.len() > 0 {
237                    print_indented!(self, "args: [", depth_lvl + 1);
238                    for arg in args.iter() {
239                        self.print_expr(*arg, depth_lvl + 2);
240                    }
241                    print_indented!(self, "]", depth_lvl + 1);
242                } else {
243                    print_indented!(self, "args: []", depth_lvl + 1);
244                }
245
246                print_indented!(self, "}", depth_lvl);
247            }
248            ByUse { expr, span } => {
249                print_indented!(self, "ByUse {", depth_lvl);
250                print_indented!(self, "expr:", depth_lvl + 1);
251                self.print_expr(*expr, depth_lvl + 2);
252                print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
253                print_indented!(self, "}", depth_lvl);
254            }
255            Deref { arg } => {
256                print_indented!(self, "Deref {", depth_lvl);
257                self.print_expr(*arg, depth_lvl + 1);
258                print_indented!(self, "}", depth_lvl);
259            }
260            Binary { op, lhs, rhs } => {
261                print_indented!(self, "Binary {", depth_lvl);
262                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
263                print_indented!(self, "lhs:", depth_lvl + 1);
264                self.print_expr(*lhs, depth_lvl + 2);
265                print_indented!(self, "rhs:", depth_lvl + 1);
266                self.print_expr(*rhs, depth_lvl + 2);
267                print_indented!(self, "}", depth_lvl);
268            }
269            LogicalOp { op, lhs, rhs } => {
270                print_indented!(self, "LogicalOp {", depth_lvl);
271                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
272                print_indented!(self, "lhs:", depth_lvl + 1);
273                self.print_expr(*lhs, depth_lvl + 2);
274                print_indented!(self, "rhs:", depth_lvl + 1);
275                self.print_expr(*rhs, depth_lvl + 2);
276                print_indented!(self, "}", depth_lvl);
277            }
278            Unary { op, arg } => {
279                print_indented!(self, "Unary {", depth_lvl);
280                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
281                print_indented!(self, "arg:", depth_lvl + 1);
282                self.print_expr(*arg, depth_lvl + 2);
283                print_indented!(self, "}", depth_lvl);
284            }
285            Cast { source } => {
286                print_indented!(self, "Cast {", depth_lvl);
287                print_indented!(self, "source:", depth_lvl + 1);
288                self.print_expr(*source, depth_lvl + 2);
289                print_indented!(self, "}", depth_lvl);
290            }
291            Use { source } => {
292                print_indented!(self, "Use {", depth_lvl);
293                print_indented!(self, "source:", depth_lvl + 1);
294                self.print_expr(*source, depth_lvl + 2);
295                print_indented!(self, "}", depth_lvl);
296            }
297            NeverToAny { source } => {
298                print_indented!(self, "NeverToAny {", depth_lvl);
299                print_indented!(self, "source:", depth_lvl + 1);
300                self.print_expr(*source, depth_lvl + 2);
301                print_indented!(self, "}", depth_lvl);
302            }
303            PointerCoercion { cast, is_from_as_cast, source } => {
304                print_indented!(self, "Pointer {", depth_lvl);
305                print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1);
306                print_indented!(
307                    self,
308                    format!("is_from_as_cast: {:?}", is_from_as_cast),
309                    depth_lvl + 1
310                );
311                print_indented!(self, "source:", depth_lvl + 1);
312                self.print_expr(*source, depth_lvl + 2);
313                print_indented!(self, "}", depth_lvl);
314            }
315            Loop { body } => {
316                print_indented!(self, "Loop (", depth_lvl);
317                print_indented!(self, "body:", depth_lvl + 1);
318                self.print_expr(*body, depth_lvl + 2);
319                print_indented!(self, ")", depth_lvl);
320            }
321            LoopMatch { state, region_scope, match_data } => {
322                print_indented!(self, "LoopMatch {", depth_lvl);
323                print_indented!(self, "state:", depth_lvl + 1);
324                self.print_expr(*state, depth_lvl + 2);
325                print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1);
326                print_indented!(self, "match_data:", depth_lvl + 1);
327                print_indented!(self, "LoopMatchMatchData {", depth_lvl + 2);
328                print_indented!(self, format!("span: {:?}", match_data.span), depth_lvl + 3);
329                print_indented!(self, "scrutinee:", depth_lvl + 3);
330                self.print_expr(match_data.scrutinee, depth_lvl + 4);
331
332                print_indented!(self, "arms: [", depth_lvl + 3);
333                for arm_id in match_data.arms.iter() {
334                    self.print_arm(*arm_id, depth_lvl + 4);
335                }
336                print_indented!(self, "]", depth_lvl + 3);
337                print_indented!(self, "}", depth_lvl + 2);
338                print_indented!(self, "}", depth_lvl);
339            }
340            Let { expr, pat } => {
341                print_indented!(self, "Let {", depth_lvl);
342                print_indented!(self, "expr:", depth_lvl + 1);
343                self.print_expr(*expr, depth_lvl + 2);
344                print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1);
345                print_indented!(self, "}", depth_lvl);
346            }
347            Match { scrutinee, arms, .. } => {
348                print_indented!(self, "Match {", depth_lvl);
349                print_indented!(self, "scrutinee:", depth_lvl + 1);
350                self.print_expr(*scrutinee, depth_lvl + 2);
351
352                print_indented!(self, "arms: [", depth_lvl + 1);
353                for arm_id in arms.iter() {
354                    self.print_arm(*arm_id, depth_lvl + 2);
355                }
356                print_indented!(self, "]", depth_lvl + 1);
357                print_indented!(self, "}", depth_lvl);
358            }
359            Block { block } => self.print_block(*block, depth_lvl),
360            Assign { lhs, rhs } => {
361                print_indented!(self, "Assign {", depth_lvl);
362                print_indented!(self, "lhs:", depth_lvl + 1);
363                self.print_expr(*lhs, depth_lvl + 2);
364                print_indented!(self, "rhs:", depth_lvl + 1);
365                self.print_expr(*rhs, depth_lvl + 2);
366                print_indented!(self, "}", depth_lvl);
367            }
368            AssignOp { op, lhs, rhs } => {
369                print_indented!(self, "AssignOp {", depth_lvl);
370                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
371                print_indented!(self, "lhs:", depth_lvl + 1);
372                self.print_expr(*lhs, depth_lvl + 2);
373                print_indented!(self, "rhs:", depth_lvl + 1);
374                self.print_expr(*rhs, depth_lvl + 2);
375                print_indented!(self, "}", depth_lvl);
376            }
377            Field { lhs, variant_index, name } => {
378                print_indented!(self, "Field {", depth_lvl);
379                print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 1);
380                print_indented!(self, format!("name: {:?}", name), depth_lvl + 1);
381                print_indented!(self, "lhs:", depth_lvl + 1);
382                self.print_expr(*lhs, depth_lvl + 2);
383                print_indented!(self, "}", depth_lvl);
384            }
385            Index { lhs, index } => {
386                print_indented!(self, "Index {", depth_lvl);
387                print_indented!(self, format!("index: {:?}", index), depth_lvl + 1);
388                print_indented!(self, "lhs:", depth_lvl + 1);
389                self.print_expr(*lhs, depth_lvl + 2);
390                print_indented!(self, "}", depth_lvl);
391            }
392            VarRef { id } => {
393                print_indented!(self, "VarRef {", depth_lvl);
394                print_indented!(self, format!("id: {:?}", id), depth_lvl + 1);
395                print_indented!(self, "}", depth_lvl);
396            }
397            UpvarRef { closure_def_id, var_hir_id } => {
398                print_indented!(self, "UpvarRef {", depth_lvl);
399                print_indented!(
400                    self,
401                    format!("closure_def_id: {:?}", closure_def_id),
402                    depth_lvl + 1
403                );
404                print_indented!(self, format!("var_hir_id: {:?}", var_hir_id), depth_lvl + 1);
405                print_indented!(self, "}", depth_lvl);
406            }
407            Borrow { borrow_kind, arg } => {
408                print_indented!(self, "Borrow (", depth_lvl);
409                print_indented!(self, format!("borrow_kind: {:?}", borrow_kind), depth_lvl + 1);
410                print_indented!(self, "arg:", depth_lvl + 1);
411                self.print_expr(*arg, depth_lvl + 2);
412                print_indented!(self, ")", depth_lvl);
413            }
414            RawBorrow { mutability, arg } => {
415                print_indented!(self, "RawBorrow {", depth_lvl);
416                print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 1);
417                print_indented!(self, "arg:", depth_lvl + 1);
418                self.print_expr(*arg, depth_lvl + 2);
419                print_indented!(self, "}", depth_lvl);
420            }
421            Break { label, value } => {
422                print_indented!(self, "Break (", depth_lvl);
423                print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
424
425                if let Some(value) = value {
426                    print_indented!(self, "value:", depth_lvl + 1);
427                    self.print_expr(*value, depth_lvl + 2);
428                }
429
430                print_indented!(self, ")", depth_lvl);
431            }
432            Continue { label } => {
433                print_indented!(self, "Continue {", depth_lvl);
434                print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
435                print_indented!(self, "}", depth_lvl);
436            }
437            ConstContinue { label, value } => {
438                print_indented!(self, "ConstContinue (", depth_lvl);
439                print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
440                print_indented!(self, "value:", depth_lvl + 1);
441                self.print_expr(*value, depth_lvl + 2);
442                print_indented!(self, ")", depth_lvl);
443            }
444            Return { value } => {
445                print_indented!(self, "Return {", depth_lvl);
446                print_indented!(self, "value:", depth_lvl + 1);
447
448                if let Some(value) = value {
449                    self.print_expr(*value, depth_lvl + 2);
450                }
451
452                print_indented!(self, "}", depth_lvl);
453            }
454            Become { value } => {
455                print_indented!(self, "Become {", depth_lvl);
456                print_indented!(self, "value:", depth_lvl + 1);
457                self.print_expr(*value, depth_lvl + 2);
458                print_indented!(self, "}", depth_lvl);
459            }
460            ConstBlock { did, args } => {
461                print_indented!(self, "ConstBlock {", depth_lvl);
462                print_indented!(self, format!("did: {:?}", did), depth_lvl + 1);
463                print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
464                print_indented!(self, "}", depth_lvl);
465            }
466            Repeat { value, count } => {
467                print_indented!(self, "Repeat {", depth_lvl);
468                print_indented!(self, format!("count: {:?}", count), depth_lvl + 1);
469                print_indented!(self, "value:", depth_lvl + 1);
470                self.print_expr(*value, depth_lvl + 2);
471                print_indented!(self, "}", depth_lvl);
472            }
473            Array { fields } => {
474                print_indented!(self, "Array {", depth_lvl);
475                print_indented!(self, "fields: [", depth_lvl + 1);
476                for field_id in fields.iter() {
477                    self.print_expr(*field_id, depth_lvl + 2);
478                }
479                print_indented!(self, "]", depth_lvl + 1);
480                print_indented!(self, "}", depth_lvl);
481            }
482            Tuple { fields } => {
483                print_indented!(self, "Tuple {", depth_lvl);
484                print_indented!(self, "fields: [", depth_lvl + 1);
485                for field_id in fields.iter() {
486                    self.print_expr(*field_id, depth_lvl + 2);
487                }
488                print_indented!(self, "]", depth_lvl + 1);
489                print_indented!(self, "}", depth_lvl);
490            }
491            Adt(adt_expr) => {
492                print_indented!(self, "Adt {", depth_lvl);
493                self.print_adt_expr(&**adt_expr, depth_lvl + 1);
494                print_indented!(self, "}", depth_lvl);
495            }
496            PlaceTypeAscription { source, user_ty, user_ty_span } => {
497                print_indented!(self, "PlaceTypeAscription {", depth_lvl);
498                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
499                print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
500                print_indented!(self, "source:", depth_lvl + 1);
501                self.print_expr(*source, depth_lvl + 2);
502                print_indented!(self, "}", depth_lvl);
503            }
504            ValueTypeAscription { source, user_ty, user_ty_span } => {
505                print_indented!(self, "ValueTypeAscription {", depth_lvl);
506                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
507                print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
508                print_indented!(self, "source:", depth_lvl + 1);
509                self.print_expr(*source, depth_lvl + 2);
510                print_indented!(self, "}", depth_lvl);
511            }
512            PlaceUnwrapUnsafeBinder { source } => {
513                print_indented!(self, "PlaceUnwrapUnsafeBinder {", depth_lvl);
514                print_indented!(self, "source:", depth_lvl + 1);
515                self.print_expr(*source, depth_lvl + 2);
516                print_indented!(self, "}", depth_lvl);
517            }
518            ValueUnwrapUnsafeBinder { source } => {
519                print_indented!(self, "ValueUnwrapUnsafeBinder {", depth_lvl);
520                print_indented!(self, "source:", depth_lvl + 1);
521                self.print_expr(*source, depth_lvl + 2);
522                print_indented!(self, "}", depth_lvl);
523            }
524            WrapUnsafeBinder { source } => {
525                print_indented!(self, "WrapUnsafeBinder {", depth_lvl);
526                print_indented!(self, "source:", depth_lvl + 1);
527                self.print_expr(*source, depth_lvl + 2);
528                print_indented!(self, "}", depth_lvl);
529            }
530            Closure(closure_expr) => {
531                print_indented!(self, "Closure {", depth_lvl);
532                print_indented!(self, "closure_expr:", depth_lvl + 1);
533                self.print_closure_expr(&**closure_expr, depth_lvl + 2);
534                print_indented!(self, "}", depth_lvl);
535            }
536            Literal { lit, neg } => {
537                print_indented!(
538                    self,
539                    format!("Literal( lit: {:?}, neg: {:?})\n", lit, neg),
540                    depth_lvl
541                );
542            }
543            NonHirLiteral { lit, user_ty } => {
544                print_indented!(self, "NonHirLiteral {", depth_lvl);
545                print_indented!(self, format!("lit: {:?}", lit), depth_lvl + 1);
546                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
547                print_indented!(self, "}", depth_lvl);
548            }
549            ZstLiteral { user_ty } => {
550                print_indented!(self, format!("ZstLiteral(user_ty: {:?})", user_ty), depth_lvl);
551            }
552            NamedConst { def_id, args, user_ty } => {
553                print_indented!(self, "NamedConst {", depth_lvl);
554                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
555                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
556                print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
557                print_indented!(self, "}", depth_lvl);
558            }
559            ConstParam { param, def_id } => {
560                print_indented!(self, "ConstParam {", depth_lvl);
561                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
562                print_indented!(self, format!("param: {:?}", param), depth_lvl + 1);
563                print_indented!(self, "}", depth_lvl);
564            }
565            StaticRef { alloc_id, ty, def_id } => {
566                print_indented!(self, "StaticRef {", depth_lvl);
567                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
568                print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
569                print_indented!(self, format!("alloc_id: {:?}", alloc_id), depth_lvl + 1);
570                print_indented!(self, "}", depth_lvl);
571            }
572            InlineAsm(expr) => {
573                print_indented!(self, "InlineAsm {", depth_lvl);
574                print_indented!(self, "expr:", depth_lvl + 1);
575                self.print_inline_asm_expr(&**expr, depth_lvl + 2);
576                print_indented!(self, "}", depth_lvl);
577            }
578            OffsetOf { container, fields } => {
579                print_indented!(self, "OffsetOf {", depth_lvl);
580                print_indented!(self, format!("container: {:?}", container), depth_lvl + 1);
581                print_indented!(self, "fields: [", depth_lvl + 1);
582
583                for field in fields.iter() {
584                    print_indented!(self, format!("{:?}", field), depth_lvl + 2);
585                    print_indented!(self, ",", depth_lvl + 1);
586                }
587
588                print_indented!(self, "]", depth_lvl + 1);
589                print_indented!(self, "}", depth_lvl);
590            }
591            ThreadLocalRef(def_id) => {
592                print_indented!(self, "ThreadLocalRef {", depth_lvl);
593                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
594                print_indented!(self, "}", depth_lvl);
595            }
596            Yield { value } => {
597                print_indented!(self, "Yield {", depth_lvl);
598                print_indented!(self, "value:", depth_lvl + 1);
599                self.print_expr(*value, depth_lvl + 2);
600                print_indented!(self, "}", depth_lvl);
601            }
602        }
603    }
604
605    fn print_adt_expr(&mut self, adt_expr: &AdtExpr<'tcx>, depth_lvl: usize) {
606        print_indented!(self, "adt_def:", depth_lvl);
607        self.print_adt_def(adt_expr.adt_def, depth_lvl + 1);
608        print_indented!(
609            self,
610            format!("variant_index: {:?}", adt_expr.variant_index),
611            depth_lvl + 1
612        );
613        print_indented!(self, format!("args: {:?}", adt_expr.args), depth_lvl + 1);
614        print_indented!(self, format!("user_ty: {:?}", adt_expr.user_ty), depth_lvl + 1);
615
616        for (i, field_expr) in adt_expr.fields.iter().enumerate() {
617            print_indented!(self, format!("field {}:", i), depth_lvl + 1);
618            self.print_expr(field_expr.expr, depth_lvl + 2);
619        }
620
621        match adt_expr.base {
622            AdtExprBase::Base(ref base) => {
623                print_indented!(self, "base:", depth_lvl + 1);
624                self.print_fru_info(base, depth_lvl + 2);
625            }
626            AdtExprBase::DefaultFields(_) => {
627                print_indented!(self, "base: {{ defaulted fields }}", depth_lvl + 1);
628            }
629            AdtExprBase::None => {
630                print_indented!(self, "base: None", depth_lvl + 1);
631            }
632        }
633    }
634
635    fn print_adt_def(&mut self, adt_def: ty::AdtDef<'tcx>, depth_lvl: usize) {
636        print_indented!(self, "AdtDef {", depth_lvl);
637        print_indented!(self, format!("did: {:?}", adt_def.did()), depth_lvl + 1);
638        print_indented!(self, format!("variants: {:?}", adt_def.variants()), depth_lvl + 1);
639        print_indented!(self, format!("flags: {:?}", adt_def.flags()), depth_lvl + 1);
640        print_indented!(self, format!("repr: {:?}", adt_def.repr()), depth_lvl + 1);
641    }
642
643    fn print_fru_info(&mut self, fru_info: &FruInfo<'tcx>, depth_lvl: usize) {
644        print_indented!(self, "FruInfo {", depth_lvl);
645        print_indented!(self, "base: ", depth_lvl + 1);
646        self.print_expr(fru_info.base, depth_lvl + 2);
647        print_indented!(self, "field_types: [", depth_lvl + 1);
648        for ty in fru_info.field_types.iter() {
649            print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
650        }
651        print_indented!(self, "}", depth_lvl);
652    }
653
654    fn print_arm(&mut self, arm_id: ArmId, depth_lvl: usize) {
655        print_indented!(self, "Arm {", depth_lvl);
656
657        let arm = &self.thir.arms[arm_id];
658        let Arm { pattern, guard, body, lint_level, scope, span } = arm;
659
660        print_indented!(self, "pattern: ", depth_lvl + 1);
661        self.print_pat(pattern, depth_lvl + 2);
662
663        if let Some(guard) = *guard {
664            print_indented!(self, "guard: ", depth_lvl + 1);
665            self.print_expr(guard, depth_lvl + 2);
666        } else {
667            print_indented!(self, "guard: None", depth_lvl + 1);
668        }
669
670        print_indented!(self, "body: ", depth_lvl + 1);
671        self.print_expr(*body, depth_lvl + 2);
672        print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1);
673        print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 1);
674        print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
675        print_indented!(self, "}", depth_lvl);
676    }
677
678    fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
679        let &Pat { ty, span, ref kind } = pat;
680
681        print_indented!(self, "Pat: {", depth_lvl);
682        print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
683        print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
684        self.print_pat_kind(kind, depth_lvl + 1);
685        print_indented!(self, "}", depth_lvl);
686    }
687
688    fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
689        print_indented!(self, "kind: PatKind {", depth_lvl);
690
691        match pat_kind {
692            PatKind::Missing => {
693                print_indented!(self, "Missing", depth_lvl + 1);
694            }
695            PatKind::Wild => {
696                print_indented!(self, "Wild", depth_lvl + 1);
697            }
698            PatKind::Never => {
699                print_indented!(self, "Never", depth_lvl + 1);
700            }
701            PatKind::AscribeUserType { ascription, subpattern } => {
702                print_indented!(self, "AscribeUserType: {", depth_lvl + 1);
703                print_indented!(self, format!("ascription: {:?}", ascription), depth_lvl + 2);
704                print_indented!(self, "subpattern: ", depth_lvl + 2);
705                self.print_pat(subpattern, depth_lvl + 3);
706                print_indented!(self, "}", depth_lvl + 1);
707            }
708            PatKind::Binding { name, mode, var, ty, subpattern, is_primary, is_shorthand } => {
709                print_indented!(self, "Binding {", depth_lvl + 1);
710                print_indented!(self, format!("name: {:?}", name), depth_lvl + 2);
711                print_indented!(self, format!("mode: {:?}", mode), depth_lvl + 2);
712                print_indented!(self, format!("var: {:?}", var), depth_lvl + 2);
713                print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
714                print_indented!(self, format!("is_primary: {:?}", is_primary), depth_lvl + 2);
715                print_indented!(self, format!("is_shorthand: {:?}", is_shorthand), depth_lvl + 2);
716
717                if let Some(subpattern) = subpattern {
718                    print_indented!(self, "subpattern: Some( ", depth_lvl + 2);
719                    self.print_pat(subpattern, depth_lvl + 3);
720                    print_indented!(self, ")", depth_lvl + 2);
721                } else {
722                    print_indented!(self, "subpattern: None", depth_lvl + 2);
723                }
724
725                print_indented!(self, "}", depth_lvl + 1);
726            }
727            PatKind::Variant { adt_def, args, variant_index, subpatterns } => {
728                print_indented!(self, "Variant {", depth_lvl + 1);
729                print_indented!(self, "adt_def: ", depth_lvl + 2);
730                self.print_adt_def(*adt_def, depth_lvl + 3);
731                print_indented!(self, format!("args: {:?}", args), depth_lvl + 2);
732                print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 2);
733
734                if subpatterns.len() > 0 {
735                    print_indented!(self, "subpatterns: [", depth_lvl + 2);
736                    for field_pat in subpatterns.iter() {
737                        self.print_pat(&field_pat.pattern, depth_lvl + 3);
738                    }
739                    print_indented!(self, "]", depth_lvl + 2);
740                } else {
741                    print_indented!(self, "subpatterns: []", depth_lvl + 2);
742                }
743
744                print_indented!(self, "}", depth_lvl + 1);
745            }
746            PatKind::Leaf { subpatterns } => {
747                print_indented!(self, "Leaf { ", depth_lvl + 1);
748                print_indented!(self, "subpatterns: [", depth_lvl + 2);
749                for field_pat in subpatterns.iter() {
750                    self.print_pat(&field_pat.pattern, depth_lvl + 3);
751                }
752                print_indented!(self, "]", depth_lvl + 2);
753                print_indented!(self, "}", depth_lvl + 1);
754            }
755            PatKind::Deref { subpattern } => {
756                print_indented!(self, "Deref { ", depth_lvl + 1);
757                print_indented!(self, "subpattern:", depth_lvl + 2);
758                self.print_pat(subpattern, depth_lvl + 2);
759                print_indented!(self, "}", depth_lvl + 1);
760            }
761            PatKind::DerefPattern { subpattern, .. } => {
762                print_indented!(self, "DerefPattern { ", depth_lvl + 1);
763                print_indented!(self, "subpattern:", depth_lvl + 2);
764                self.print_pat(subpattern, depth_lvl + 2);
765                print_indented!(self, "}", depth_lvl + 1);
766            }
767            PatKind::Constant { value } => {
768                print_indented!(self, "Constant {", depth_lvl + 1);
769                print_indented!(self, format!("value: {}", value), depth_lvl + 2);
770                print_indented!(self, "}", depth_lvl + 1);
771            }
772            PatKind::ExpandedConstant { def_id, subpattern } => {
773                print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
774                print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
775                print_indented!(self, "subpattern:", depth_lvl + 2);
776                self.print_pat(subpattern, depth_lvl + 2);
777                print_indented!(self, "}", depth_lvl + 1);
778            }
779            PatKind::Range(pat_range) => {
780                print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1);
781            }
782            PatKind::Slice { prefix, slice, suffix } => {
783                print_indented!(self, "Slice {", depth_lvl + 1);
784
785                print_indented!(self, "prefix: [", depth_lvl + 2);
786                for prefix_pat in prefix.iter() {
787                    self.print_pat(prefix_pat, depth_lvl + 3);
788                }
789                print_indented!(self, "]", depth_lvl + 2);
790
791                if let Some(slice) = slice {
792                    print_indented!(self, "slice: ", depth_lvl + 2);
793                    self.print_pat(slice, depth_lvl + 3);
794                }
795
796                print_indented!(self, "suffix: [", depth_lvl + 2);
797                for suffix_pat in suffix.iter() {
798                    self.print_pat(suffix_pat, depth_lvl + 3);
799                }
800                print_indented!(self, "]", depth_lvl + 2);
801
802                print_indented!(self, "}", depth_lvl + 1);
803            }
804            PatKind::Array { prefix, slice, suffix } => {
805                print_indented!(self, "Array {", depth_lvl + 1);
806
807                print_indented!(self, "prefix: [", depth_lvl + 2);
808                for prefix_pat in prefix.iter() {
809                    self.print_pat(prefix_pat, depth_lvl + 3);
810                }
811                print_indented!(self, "]", depth_lvl + 2);
812
813                if let Some(slice) = slice {
814                    print_indented!(self, "slice: ", depth_lvl + 2);
815                    self.print_pat(slice, depth_lvl + 3);
816                }
817
818                print_indented!(self, "suffix: [", depth_lvl + 2);
819                for suffix_pat in suffix.iter() {
820                    self.print_pat(suffix_pat, depth_lvl + 3);
821                }
822                print_indented!(self, "]", depth_lvl + 2);
823
824                print_indented!(self, "}", depth_lvl + 1);
825            }
826            PatKind::Or { pats } => {
827                print_indented!(self, "Or {", depth_lvl + 1);
828                print_indented!(self, "pats: [", depth_lvl + 2);
829                for pat in pats.iter() {
830                    self.print_pat(pat, depth_lvl + 3);
831                }
832                print_indented!(self, "]", depth_lvl + 2);
833                print_indented!(self, "}", depth_lvl + 1);
834            }
835            PatKind::Error(_) => {
836                print_indented!(self, "Error", depth_lvl + 1);
837            }
838        }
839
840        print_indented!(self, "}", depth_lvl);
841    }
842
843    fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) {
844        let ClosureExpr { closure_id, args, upvars, movability, fake_reads } = expr;
845
846        print_indented!(self, "ClosureExpr {", depth_lvl);
847        print_indented!(self, format!("closure_id: {:?}", closure_id), depth_lvl + 1);
848        print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
849
850        if upvars.len() > 0 {
851            print_indented!(self, "upvars: [", depth_lvl + 1);
852            for upvar in upvars.iter() {
853                self.print_expr(*upvar, depth_lvl + 2);
854                print_indented!(self, ",", depth_lvl + 1);
855            }
856            print_indented!(self, "]", depth_lvl + 1);
857        } else {
858            print_indented!(self, "upvars: []", depth_lvl + 1);
859        }
860
861        print_indented!(self, format!("movability: {:?}", movability), depth_lvl + 1);
862
863        if fake_reads.len() > 0 {
864            print_indented!(self, "fake_reads: [", depth_lvl + 1);
865            for (fake_read_expr, cause, hir_id) in fake_reads.iter() {
866                print_indented!(self, "(", depth_lvl + 2);
867                self.print_expr(*fake_read_expr, depth_lvl + 3);
868                print_indented!(self, ",", depth_lvl + 2);
869                print_indented!(self, format!("cause: {:?}", cause), depth_lvl + 3);
870                print_indented!(self, ",", depth_lvl + 2);
871                print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 3);
872                print_indented!(self, "),", depth_lvl + 2);
873            }
874            print_indented!(self, "]", depth_lvl + 1);
875        } else {
876            print_indented!(self, "fake_reads: []", depth_lvl + 1);
877        }
878
879        print_indented!(self, "}", depth_lvl);
880    }
881
882    fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) {
883        let InlineAsmExpr { asm_macro, template, operands, options, line_spans } = expr;
884
885        print_indented!(self, "InlineAsmExpr {", depth_lvl);
886
887        print_indented!(self, format!("asm_macro: {:?}", asm_macro), depth_lvl + 1);
888
889        print_indented!(self, "template: [", depth_lvl + 1);
890        for template_piece in template.iter() {
891            print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2);
892        }
893        print_indented!(self, "]", depth_lvl + 1);
894
895        print_indented!(self, "operands: [", depth_lvl + 1);
896        for operand in operands.iter() {
897            self.print_inline_operand(operand, depth_lvl + 2);
898        }
899        print_indented!(self, "]", depth_lvl + 1);
900
901        print_indented!(self, format!("options: {:?}", options), depth_lvl + 1);
902        print_indented!(self, format!("line_spans: {:?}", line_spans), depth_lvl + 1);
903    }
904
905    fn print_inline_operand(&mut self, operand: &InlineAsmOperand<'tcx>, depth_lvl: usize) {
906        match operand {
907            InlineAsmOperand::In { reg, expr } => {
908                print_indented!(self, "InlineAsmOperand::In {", depth_lvl);
909                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
910                print_indented!(self, "expr: ", depth_lvl + 1);
911                self.print_expr(*expr, depth_lvl + 2);
912                print_indented!(self, "}", depth_lvl + 1);
913            }
914            InlineAsmOperand::Out { reg, late, expr } => {
915                print_indented!(self, "InlineAsmOperand::Out {", depth_lvl);
916                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
917                print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
918
919                if let Some(out) = expr {
920                    print_indented!(self, "place: Some( ", depth_lvl + 1);
921                    self.print_expr(*out, depth_lvl + 2);
922                    print_indented!(self, ")", depth_lvl + 1);
923                } else {
924                    print_indented!(self, "place: None", depth_lvl + 1);
925                }
926                print_indented!(self, "}", depth_lvl + 1);
927            }
928            InlineAsmOperand::InOut { reg, late, expr } => {
929                print_indented!(self, "InlineAsmOperand::InOut {", depth_lvl);
930                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
931                print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
932                print_indented!(self, "expr: ", depth_lvl + 1);
933                self.print_expr(*expr, depth_lvl + 2);
934                print_indented!(self, "}", depth_lvl + 1);
935            }
936            InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
937                print_indented!(self, "InlineAsmOperand::SplitInOut {", depth_lvl);
938                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
939                print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
940                print_indented!(self, "in_expr: ", depth_lvl + 1);
941                self.print_expr(*in_expr, depth_lvl + 2);
942
943                if let Some(out_expr) = out_expr {
944                    print_indented!(self, "out_expr: Some( ", depth_lvl + 1);
945                    self.print_expr(*out_expr, depth_lvl + 2);
946                    print_indented!(self, ")", depth_lvl + 1);
947                } else {
948                    print_indented!(self, "out_expr: None", depth_lvl + 1);
949                }
950
951                print_indented!(self, "}", depth_lvl + 1);
952            }
953            InlineAsmOperand::Const { value, span } => {
954                print_indented!(self, "InlineAsmOperand::Const {", depth_lvl);
955                print_indented!(self, format!("value: {:?}", value), depth_lvl + 1);
956                print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
957                print_indented!(self, "}", depth_lvl + 1);
958            }
959            InlineAsmOperand::SymFn { value } => {
960                print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl);
961                print_indented!(self, "value: ", depth_lvl + 1);
962                self.print_expr(*value, depth_lvl + 2);
963                print_indented!(self, "}", depth_lvl + 1);
964            }
965            InlineAsmOperand::SymStatic { def_id } => {
966                print_indented!(self, "InlineAsmOperand::SymStatic {", depth_lvl);
967                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
968                print_indented!(self, "}", depth_lvl + 1);
969            }
970            InlineAsmOperand::Label { block } => {
971                print_indented!(self, "InlineAsmOperand::Block {", depth_lvl);
972                print_indented!(self, "block:", depth_lvl + 1);
973                self.print_block(*block, depth_lvl + 2);
974                print_indented!(self, "}", depth_lvl + 1);
975            }
976        }
977    }
978}