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