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