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            Deref { arg } => {
250                print_indented!(self, "Deref {", depth_lvl);
251                self.print_expr(*arg, depth_lvl + 1);
252                print_indented!(self, "}", depth_lvl);
253            }
254            Binary { op, lhs, rhs } => {
255                print_indented!(self, "Binary {", depth_lvl);
256                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
257                print_indented!(self, "lhs:", depth_lvl + 1);
258                self.print_expr(*lhs, depth_lvl + 2);
259                print_indented!(self, "rhs:", depth_lvl + 1);
260                self.print_expr(*rhs, depth_lvl + 2);
261                print_indented!(self, "}", depth_lvl);
262            }
263            LogicalOp { op, lhs, rhs } => {
264                print_indented!(self, "LogicalOp {", depth_lvl);
265                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
266                print_indented!(self, "lhs:", depth_lvl + 1);
267                self.print_expr(*lhs, depth_lvl + 2);
268                print_indented!(self, "rhs:", depth_lvl + 1);
269                self.print_expr(*rhs, depth_lvl + 2);
270                print_indented!(self, "}", depth_lvl);
271            }
272            Unary { op, arg } => {
273                print_indented!(self, "Unary {", depth_lvl);
274                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
275                print_indented!(self, "arg:", depth_lvl + 1);
276                self.print_expr(*arg, depth_lvl + 2);
277                print_indented!(self, "}", depth_lvl);
278            }
279            Cast { source } => {
280                print_indented!(self, "Cast {", depth_lvl);
281                print_indented!(self, "source:", depth_lvl + 1);
282                self.print_expr(*source, depth_lvl + 2);
283                print_indented!(self, "}", depth_lvl);
284            }
285            Use { source } => {
286                print_indented!(self, "Use {", depth_lvl);
287                print_indented!(self, "source:", depth_lvl + 1);
288                self.print_expr(*source, depth_lvl + 2);
289                print_indented!(self, "}", depth_lvl);
290            }
291            NeverToAny { source } => {
292                print_indented!(self, "NeverToAny {", depth_lvl);
293                print_indented!(self, "source:", depth_lvl + 1);
294                self.print_expr(*source, depth_lvl + 2);
295                print_indented!(self, "}", depth_lvl);
296            }
297            PointerCoercion { cast, is_from_as_cast, source } => {
298                print_indented!(self, "Pointer {", depth_lvl);
299                print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1);
300                print_indented!(
301                    self,
302                    format!("is_from_as_cast: {:?}", is_from_as_cast),
303                    depth_lvl + 1
304                );
305                print_indented!(self, "source:", depth_lvl + 1);
306                self.print_expr(*source, depth_lvl + 2);
307                print_indented!(self, "}", depth_lvl);
308            }
309            Loop { body } => {
310                print_indented!(self, "Loop (", depth_lvl);
311                print_indented!(self, "body:", depth_lvl + 1);
312                self.print_expr(*body, depth_lvl + 2);
313                print_indented!(self, ")", depth_lvl);
314            }
315            Let { expr, pat } => {
316                print_indented!(self, "Let {", depth_lvl);
317                print_indented!(self, "expr:", depth_lvl + 1);
318                self.print_expr(*expr, depth_lvl + 2);
319                print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1);
320                print_indented!(self, "}", depth_lvl);
321            }
322            Match { scrutinee, arms, .. } => {
323                print_indented!(self, "Match {", depth_lvl);
324                print_indented!(self, "scrutinee:", depth_lvl + 1);
325                self.print_expr(*scrutinee, depth_lvl + 2);
326
327                print_indented!(self, "arms: [", depth_lvl + 1);
328                for arm_id in arms.iter() {
329                    self.print_arm(*arm_id, depth_lvl + 2);
330                }
331                print_indented!(self, "]", depth_lvl + 1);
332                print_indented!(self, "}", depth_lvl);
333            }
334            Block { block } => self.print_block(*block, depth_lvl),
335            Assign { lhs, rhs } => {
336                print_indented!(self, "Assign {", depth_lvl);
337                print_indented!(self, "lhs:", depth_lvl + 1);
338                self.print_expr(*lhs, depth_lvl + 2);
339                print_indented!(self, "rhs:", depth_lvl + 1);
340                self.print_expr(*rhs, depth_lvl + 2);
341                print_indented!(self, "}", depth_lvl);
342            }
343            AssignOp { op, lhs, rhs } => {
344                print_indented!(self, "AssignOp {", depth_lvl);
345                print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
346                print_indented!(self, "lhs:", depth_lvl + 1);
347                self.print_expr(*lhs, depth_lvl + 2);
348                print_indented!(self, "rhs:", depth_lvl + 1);
349                self.print_expr(*rhs, depth_lvl + 2);
350                print_indented!(self, "}", depth_lvl);
351            }
352            Field { lhs, variant_index, name } => {
353                print_indented!(self, "Field {", depth_lvl);
354                print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 1);
355                print_indented!(self, format!("name: {:?}", name), depth_lvl + 1);
356                print_indented!(self, "lhs:", depth_lvl + 1);
357                self.print_expr(*lhs, depth_lvl + 2);
358                print_indented!(self, "}", depth_lvl);
359            }
360            Index { lhs, index } => {
361                print_indented!(self, "Index {", depth_lvl);
362                print_indented!(self, format!("index: {:?}", index), 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            VarRef { id } => {
368                print_indented!(self, "VarRef {", depth_lvl);
369                print_indented!(self, format!("id: {:?}", id), depth_lvl + 1);
370                print_indented!(self, "}", depth_lvl);
371            }
372            UpvarRef { closure_def_id, var_hir_id } => {
373                print_indented!(self, "UpvarRef {", depth_lvl);
374                print_indented!(
375                    self,
376                    format!("closure_def_id: {:?}", closure_def_id),
377                    depth_lvl + 1
378                );
379                print_indented!(self, format!("var_hir_id: {:?}", var_hir_id), depth_lvl + 1);
380                print_indented!(self, "}", depth_lvl);
381            }
382            Borrow { borrow_kind, arg } => {
383                print_indented!(self, "Borrow (", depth_lvl);
384                print_indented!(self, format!("borrow_kind: {:?}", borrow_kind), depth_lvl + 1);
385                print_indented!(self, "arg:", depth_lvl + 1);
386                self.print_expr(*arg, depth_lvl + 2);
387                print_indented!(self, ")", depth_lvl);
388            }
389            RawBorrow { mutability, arg } => {
390                print_indented!(self, "RawBorrow {", depth_lvl);
391                print_indented!(self, format!("mutability: {:?}", mutability), 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            Break { label, value } => {
397                print_indented!(self, "Break (", depth_lvl);
398                print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
399
400                if let Some(value) = value {
401                    print_indented!(self, "value:", depth_lvl + 1);
402                    self.print_expr(*value, depth_lvl + 2);
403                }
404
405                print_indented!(self, ")", depth_lvl);
406            }
407            Continue { label } => {
408                print_indented!(self, "Continue {", depth_lvl);
409                print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
410                print_indented!(self, "}", depth_lvl);
411            }
412            Return { value } => {
413                print_indented!(self, "Return {", depth_lvl);
414                print_indented!(self, "value:", depth_lvl + 1);
415
416                if let Some(value) = value {
417                    self.print_expr(*value, depth_lvl + 2);
418                }
419
420                print_indented!(self, "}", depth_lvl);
421            }
422            Become { value } => {
423                print_indented!(self, "Become {", depth_lvl);
424                print_indented!(self, "value:", depth_lvl + 1);
425                self.print_expr(*value, depth_lvl + 2);
426                print_indented!(self, "}", depth_lvl);
427            }
428            ConstBlock { did, args } => {
429                print_indented!(self, "ConstBlock {", depth_lvl);
430                print_indented!(self, format!("did: {:?}", did), depth_lvl + 1);
431                print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
432                print_indented!(self, "}", depth_lvl);
433            }
434            Repeat { value, count } => {
435                print_indented!(self, "Repeat {", depth_lvl);
436                print_indented!(self, format!("count: {:?}", count), depth_lvl + 1);
437                print_indented!(self, "value:", depth_lvl + 1);
438                self.print_expr(*value, depth_lvl + 2);
439                print_indented!(self, "}", depth_lvl);
440            }
441            Array { fields } => {
442                print_indented!(self, "Array {", depth_lvl);
443                print_indented!(self, "fields: [", depth_lvl + 1);
444                for field_id in fields.iter() {
445                    self.print_expr(*field_id, depth_lvl + 2);
446                }
447                print_indented!(self, "]", depth_lvl + 1);
448                print_indented!(self, "}", depth_lvl);
449            }
450            Tuple { fields } => {
451                print_indented!(self, "Tuple {", depth_lvl);
452                print_indented!(self, "fields: [", depth_lvl + 1);
453                for field_id in fields.iter() {
454                    self.print_expr(*field_id, depth_lvl + 2);
455                }
456                print_indented!(self, "]", depth_lvl + 1);
457                print_indented!(self, "}", depth_lvl);
458            }
459            Adt(adt_expr) => {
460                print_indented!(self, "Adt {", depth_lvl);
461                self.print_adt_expr(&**adt_expr, depth_lvl + 1);
462                print_indented!(self, "}", depth_lvl);
463            }
464            PlaceTypeAscription { source, user_ty, user_ty_span } => {
465                print_indented!(self, "PlaceTypeAscription {", depth_lvl);
466                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
467                print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
468                print_indented!(self, "source:", depth_lvl + 1);
469                self.print_expr(*source, depth_lvl + 2);
470                print_indented!(self, "}", depth_lvl);
471            }
472            ValueTypeAscription { source, user_ty, user_ty_span } => {
473                print_indented!(self, "ValueTypeAscription {", depth_lvl);
474                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
475                print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
476                print_indented!(self, "source:", depth_lvl + 1);
477                self.print_expr(*source, depth_lvl + 2);
478                print_indented!(self, "}", depth_lvl);
479            }
480            PlaceUnwrapUnsafeBinder { source } => {
481                print_indented!(self, "PlaceUnwrapUnsafeBinder {", depth_lvl);
482                print_indented!(self, "source:", depth_lvl + 1);
483                self.print_expr(*source, depth_lvl + 2);
484                print_indented!(self, "}", depth_lvl);
485            }
486            ValueUnwrapUnsafeBinder { source } => {
487                print_indented!(self, "ValueUnwrapUnsafeBinder {", depth_lvl);
488                print_indented!(self, "source:", depth_lvl + 1);
489                self.print_expr(*source, depth_lvl + 2);
490                print_indented!(self, "}", depth_lvl);
491            }
492            WrapUnsafeBinder { source } => {
493                print_indented!(self, "WrapUnsafeBinder {", depth_lvl);
494                print_indented!(self, "source:", depth_lvl + 1);
495                self.print_expr(*source, depth_lvl + 2);
496                print_indented!(self, "}", depth_lvl);
497            }
498            Closure(closure_expr) => {
499                print_indented!(self, "Closure {", depth_lvl);
500                print_indented!(self, "closure_expr:", depth_lvl + 1);
501                self.print_closure_expr(&**closure_expr, depth_lvl + 2);
502                print_indented!(self, "}", depth_lvl);
503            }
504            Literal { lit, neg } => {
505                print_indented!(
506                    self,
507                    format!("Literal( lit: {:?}, neg: {:?})\n", lit, neg),
508                    depth_lvl
509                );
510            }
511            NonHirLiteral { lit, user_ty } => {
512                print_indented!(self, "NonHirLiteral {", depth_lvl);
513                print_indented!(self, format!("lit: {:?}", lit), depth_lvl + 1);
514                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
515                print_indented!(self, "}", depth_lvl);
516            }
517            ZstLiteral { user_ty } => {
518                print_indented!(self, format!("ZstLiteral(user_ty: {:?})", user_ty), depth_lvl);
519            }
520            NamedConst { def_id, args, user_ty } => {
521                print_indented!(self, "NamedConst {", depth_lvl);
522                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
523                print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
524                print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
525                print_indented!(self, "}", depth_lvl);
526            }
527            ConstParam { param, def_id } => {
528                print_indented!(self, "ConstParam {", depth_lvl);
529                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
530                print_indented!(self, format!("param: {:?}", param), depth_lvl + 1);
531                print_indented!(self, "}", depth_lvl);
532            }
533            StaticRef { alloc_id, ty, def_id } => {
534                print_indented!(self, "StaticRef {", depth_lvl);
535                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
536                print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
537                print_indented!(self, format!("alloc_id: {:?}", alloc_id), depth_lvl + 1);
538                print_indented!(self, "}", depth_lvl);
539            }
540            InlineAsm(expr) => {
541                print_indented!(self, "InlineAsm {", depth_lvl);
542                print_indented!(self, "expr:", depth_lvl + 1);
543                self.print_inline_asm_expr(&**expr, depth_lvl + 2);
544                print_indented!(self, "}", depth_lvl);
545            }
546            OffsetOf { container, fields } => {
547                print_indented!(self, "OffsetOf {", depth_lvl);
548                print_indented!(self, format!("container: {:?}", container), depth_lvl + 1);
549                print_indented!(self, "fields: [", depth_lvl + 1);
550
551                for field in fields.iter() {
552                    print_indented!(self, format!("{:?}", field), depth_lvl + 2);
553                    print_indented!(self, ",", depth_lvl + 1);
554                }
555
556                print_indented!(self, "]", depth_lvl + 1);
557                print_indented!(self, "}", depth_lvl);
558            }
559            ThreadLocalRef(def_id) => {
560                print_indented!(self, "ThreadLocalRef {", depth_lvl);
561                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
562                print_indented!(self, "}", depth_lvl);
563            }
564            Yield { value } => {
565                print_indented!(self, "Yield {", depth_lvl);
566                print_indented!(self, "value:", depth_lvl + 1);
567                self.print_expr(*value, depth_lvl + 2);
568                print_indented!(self, "}", depth_lvl);
569            }
570        }
571    }
572
573    fn print_adt_expr(&mut self, adt_expr: &AdtExpr<'tcx>, depth_lvl: usize) {
574        print_indented!(self, "adt_def:", depth_lvl);
575        self.print_adt_def(adt_expr.adt_def, depth_lvl + 1);
576        print_indented!(
577            self,
578            format!("variant_index: {:?}", adt_expr.variant_index),
579            depth_lvl + 1
580        );
581        print_indented!(self, format!("args: {:?}", adt_expr.args), depth_lvl + 1);
582        print_indented!(self, format!("user_ty: {:?}", adt_expr.user_ty), depth_lvl + 1);
583
584        for (i, field_expr) in adt_expr.fields.iter().enumerate() {
585            print_indented!(self, format!("field {}:", i), depth_lvl + 1);
586            self.print_expr(field_expr.expr, depth_lvl + 2);
587        }
588
589        match adt_expr.base {
590            AdtExprBase::Base(ref base) => {
591                print_indented!(self, "base:", depth_lvl + 1);
592                self.print_fru_info(base, depth_lvl + 2);
593            }
594            AdtExprBase::DefaultFields(_) => {
595                print_indented!(self, "base: {{ defaulted fields }}", depth_lvl + 1);
596            }
597            AdtExprBase::None => {
598                print_indented!(self, "base: None", depth_lvl + 1);
599            }
600        }
601    }
602
603    fn print_adt_def(&mut self, adt_def: ty::AdtDef<'tcx>, depth_lvl: usize) {
604        print_indented!(self, "AdtDef {", depth_lvl);
605        print_indented!(self, format!("did: {:?}", adt_def.did()), depth_lvl + 1);
606        print_indented!(self, format!("variants: {:?}", adt_def.variants()), depth_lvl + 1);
607        print_indented!(self, format!("flags: {:?}", adt_def.flags()), depth_lvl + 1);
608        print_indented!(self, format!("repr: {:?}", adt_def.repr()), depth_lvl + 1);
609    }
610
611    fn print_fru_info(&mut self, fru_info: &FruInfo<'tcx>, depth_lvl: usize) {
612        print_indented!(self, "FruInfo {", depth_lvl);
613        print_indented!(self, "base: ", depth_lvl + 1);
614        self.print_expr(fru_info.base, depth_lvl + 2);
615        print_indented!(self, "field_types: [", depth_lvl + 1);
616        for ty in fru_info.field_types.iter() {
617            print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
618        }
619        print_indented!(self, "}", depth_lvl);
620    }
621
622    fn print_arm(&mut self, arm_id: ArmId, depth_lvl: usize) {
623        print_indented!(self, "Arm {", depth_lvl);
624
625        let arm = &self.thir.arms[arm_id];
626        let Arm { pattern, guard, body, lint_level, scope, span } = arm;
627
628        print_indented!(self, "pattern: ", depth_lvl + 1);
629        self.print_pat(pattern, depth_lvl + 2);
630
631        if let Some(guard) = *guard {
632            print_indented!(self, "guard: ", depth_lvl + 1);
633            self.print_expr(guard, depth_lvl + 2);
634        } else {
635            print_indented!(self, "guard: None", depth_lvl + 1);
636        }
637
638        print_indented!(self, "body: ", depth_lvl + 1);
639        self.print_expr(*body, depth_lvl + 2);
640        print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1);
641        print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 1);
642        print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
643        print_indented!(self, "}", depth_lvl);
644    }
645
646    fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
647        let &Pat { ty, span, ref kind } = pat;
648
649        print_indented!(self, "Pat: {", depth_lvl);
650        print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
651        print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
652        self.print_pat_kind(kind, depth_lvl + 1);
653        print_indented!(self, "}", depth_lvl);
654    }
655
656    fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
657        print_indented!(self, "kind: PatKind {", depth_lvl);
658
659        match pat_kind {
660            PatKind::Wild => {
661                print_indented!(self, "Wild", depth_lvl + 1);
662            }
663            PatKind::Never => {
664                print_indented!(self, "Never", depth_lvl + 1);
665            }
666            PatKind::AscribeUserType { ascription, subpattern } => {
667                print_indented!(self, "AscribeUserType: {", depth_lvl + 1);
668                print_indented!(self, format!("ascription: {:?}", ascription), depth_lvl + 2);
669                print_indented!(self, "subpattern: ", depth_lvl + 2);
670                self.print_pat(subpattern, depth_lvl + 3);
671                print_indented!(self, "}", depth_lvl + 1);
672            }
673            PatKind::Binding { name, mode, var, ty, subpattern, is_primary } => {
674                print_indented!(self, "Binding {", depth_lvl + 1);
675                print_indented!(self, format!("name: {:?}", name), depth_lvl + 2);
676                print_indented!(self, format!("mode: {:?}", mode), depth_lvl + 2);
677                print_indented!(self, format!("var: {:?}", var), depth_lvl + 2);
678                print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
679                print_indented!(self, format!("is_primary: {:?}", is_primary), depth_lvl + 2);
680
681                if let Some(subpattern) = subpattern {
682                    print_indented!(self, "subpattern: Some( ", depth_lvl + 2);
683                    self.print_pat(subpattern, depth_lvl + 3);
684                    print_indented!(self, ")", depth_lvl + 2);
685                } else {
686                    print_indented!(self, "subpattern: None", depth_lvl + 2);
687                }
688
689                print_indented!(self, "}", depth_lvl + 1);
690            }
691            PatKind::Variant { adt_def, args, variant_index, subpatterns } => {
692                print_indented!(self, "Variant {", depth_lvl + 1);
693                print_indented!(self, "adt_def: ", depth_lvl + 2);
694                self.print_adt_def(*adt_def, depth_lvl + 3);
695                print_indented!(self, format!("args: {:?}", args), depth_lvl + 2);
696                print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 2);
697
698                if subpatterns.len() > 0 {
699                    print_indented!(self, "subpatterns: [", depth_lvl + 2);
700                    for field_pat in subpatterns.iter() {
701                        self.print_pat(&field_pat.pattern, depth_lvl + 3);
702                    }
703                    print_indented!(self, "]", depth_lvl + 2);
704                } else {
705                    print_indented!(self, "subpatterns: []", depth_lvl + 2);
706                }
707
708                print_indented!(self, "}", depth_lvl + 1);
709            }
710            PatKind::Leaf { subpatterns } => {
711                print_indented!(self, "Leaf { ", depth_lvl + 1);
712                print_indented!(self, "subpatterns: [", depth_lvl + 2);
713                for field_pat in subpatterns.iter() {
714                    self.print_pat(&field_pat.pattern, depth_lvl + 3);
715                }
716                print_indented!(self, "]", depth_lvl + 2);
717                print_indented!(self, "}", depth_lvl + 1);
718            }
719            PatKind::Deref { subpattern } => {
720                print_indented!(self, "Deref { ", depth_lvl + 1);
721                print_indented!(self, "subpattern:", depth_lvl + 2);
722                self.print_pat(subpattern, depth_lvl + 2);
723                print_indented!(self, "}", depth_lvl + 1);
724            }
725            PatKind::DerefPattern { subpattern, .. } => {
726                print_indented!(self, "DerefPattern { ", depth_lvl + 1);
727                print_indented!(self, "subpattern:", depth_lvl + 2);
728                self.print_pat(subpattern, depth_lvl + 2);
729                print_indented!(self, "}", depth_lvl + 1);
730            }
731            PatKind::Constant { value } => {
732                print_indented!(self, "Constant {", depth_lvl + 1);
733                print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
734                print_indented!(self, "}", depth_lvl + 1);
735            }
736            PatKind::ExpandedConstant { def_id, is_inline, subpattern } => {
737                print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
738                print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
739                print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2);
740                print_indented!(self, "subpattern:", depth_lvl + 2);
741                self.print_pat(subpattern, depth_lvl + 2);
742                print_indented!(self, "}", depth_lvl + 1);
743            }
744            PatKind::Range(pat_range) => {
745                print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1);
746            }
747            PatKind::Slice { prefix, slice, suffix } => {
748                print_indented!(self, "Slice {", depth_lvl + 1);
749
750                print_indented!(self, "prefix: [", depth_lvl + 2);
751                for prefix_pat in prefix.iter() {
752                    self.print_pat(prefix_pat, depth_lvl + 3);
753                }
754                print_indented!(self, "]", depth_lvl + 2);
755
756                if let Some(slice) = slice {
757                    print_indented!(self, "slice: ", depth_lvl + 2);
758                    self.print_pat(slice, depth_lvl + 3);
759                }
760
761                print_indented!(self, "suffix: [", depth_lvl + 2);
762                for suffix_pat in suffix.iter() {
763                    self.print_pat(suffix_pat, depth_lvl + 3);
764                }
765                print_indented!(self, "]", depth_lvl + 2);
766
767                print_indented!(self, "}", depth_lvl + 1);
768            }
769            PatKind::Array { prefix, slice, suffix } => {
770                print_indented!(self, "Array {", depth_lvl + 1);
771
772                print_indented!(self, "prefix: [", depth_lvl + 2);
773                for prefix_pat in prefix.iter() {
774                    self.print_pat(prefix_pat, depth_lvl + 3);
775                }
776                print_indented!(self, "]", depth_lvl + 2);
777
778                if let Some(slice) = slice {
779                    print_indented!(self, "slice: ", depth_lvl + 2);
780                    self.print_pat(slice, depth_lvl + 3);
781                }
782
783                print_indented!(self, "suffix: [", depth_lvl + 2);
784                for suffix_pat in suffix.iter() {
785                    self.print_pat(suffix_pat, depth_lvl + 3);
786                }
787                print_indented!(self, "]", depth_lvl + 2);
788
789                print_indented!(self, "}", depth_lvl + 1);
790            }
791            PatKind::Or { pats } => {
792                print_indented!(self, "Or {", depth_lvl + 1);
793                print_indented!(self, "pats: [", depth_lvl + 2);
794                for pat in pats.iter() {
795                    self.print_pat(pat, depth_lvl + 3);
796                }
797                print_indented!(self, "]", depth_lvl + 2);
798                print_indented!(self, "}", depth_lvl + 1);
799            }
800            PatKind::Error(_) => {
801                print_indented!(self, "Error", depth_lvl + 1);
802            }
803        }
804
805        print_indented!(self, "}", depth_lvl);
806    }
807
808    fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) {
809        let ClosureExpr { closure_id, args, upvars, movability, fake_reads } = expr;
810
811        print_indented!(self, "ClosureExpr {", depth_lvl);
812        print_indented!(self, format!("closure_id: {:?}", closure_id), depth_lvl + 1);
813        print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
814
815        if upvars.len() > 0 {
816            print_indented!(self, "upvars: [", depth_lvl + 1);
817            for upvar in upvars.iter() {
818                self.print_expr(*upvar, depth_lvl + 2);
819                print_indented!(self, ",", depth_lvl + 1);
820            }
821            print_indented!(self, "]", depth_lvl + 1);
822        } else {
823            print_indented!(self, "upvars: []", depth_lvl + 1);
824        }
825
826        print_indented!(self, format!("movability: {:?}", movability), depth_lvl + 1);
827
828        if fake_reads.len() > 0 {
829            print_indented!(self, "fake_reads: [", depth_lvl + 1);
830            for (fake_read_expr, cause, hir_id) in fake_reads.iter() {
831                print_indented!(self, "(", depth_lvl + 2);
832                self.print_expr(*fake_read_expr, depth_lvl + 3);
833                print_indented!(self, ",", depth_lvl + 2);
834                print_indented!(self, format!("cause: {:?}", cause), depth_lvl + 3);
835                print_indented!(self, ",", depth_lvl + 2);
836                print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 3);
837                print_indented!(self, "),", depth_lvl + 2);
838            }
839            print_indented!(self, "]", depth_lvl + 1);
840        } else {
841            print_indented!(self, "fake_reads: []", depth_lvl + 1);
842        }
843
844        print_indented!(self, "}", depth_lvl);
845    }
846
847    fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) {
848        let InlineAsmExpr { asm_macro, template, operands, options, line_spans } = expr;
849
850        print_indented!(self, "InlineAsmExpr {", depth_lvl);
851
852        print_indented!(self, format!("asm_macro: {:?}", asm_macro), depth_lvl + 1);
853
854        print_indented!(self, "template: [", depth_lvl + 1);
855        for template_piece in template.iter() {
856            print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2);
857        }
858        print_indented!(self, "]", depth_lvl + 1);
859
860        print_indented!(self, "operands: [", depth_lvl + 1);
861        for operand in operands.iter() {
862            self.print_inline_operand(operand, depth_lvl + 2);
863        }
864        print_indented!(self, "]", depth_lvl + 1);
865
866        print_indented!(self, format!("options: {:?}", options), depth_lvl + 1);
867        print_indented!(self, format!("line_spans: {:?}", line_spans), depth_lvl + 1);
868    }
869
870    fn print_inline_operand(&mut self, operand: &InlineAsmOperand<'tcx>, depth_lvl: usize) {
871        match operand {
872            InlineAsmOperand::In { reg, expr } => {
873                print_indented!(self, "InlineAsmOperand::In {", depth_lvl);
874                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
875                print_indented!(self, "expr: ", depth_lvl + 1);
876                self.print_expr(*expr, depth_lvl + 2);
877                print_indented!(self, "}", depth_lvl + 1);
878            }
879            InlineAsmOperand::Out { reg, late, expr } => {
880                print_indented!(self, "InlineAsmOperand::Out {", depth_lvl);
881                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
882                print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
883
884                if let Some(out) = expr {
885                    print_indented!(self, "place: Some( ", depth_lvl + 1);
886                    self.print_expr(*out, depth_lvl + 2);
887                    print_indented!(self, ")", depth_lvl + 1);
888                } else {
889                    print_indented!(self, "place: None", depth_lvl + 1);
890                }
891                print_indented!(self, "}", depth_lvl + 1);
892            }
893            InlineAsmOperand::InOut { reg, late, expr } => {
894                print_indented!(self, "InlineAsmOperand::InOut {", depth_lvl);
895                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
896                print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
897                print_indented!(self, "expr: ", depth_lvl + 1);
898                self.print_expr(*expr, depth_lvl + 2);
899                print_indented!(self, "}", depth_lvl + 1);
900            }
901            InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
902                print_indented!(self, "InlineAsmOperand::SplitInOut {", depth_lvl);
903                print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
904                print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
905                print_indented!(self, "in_expr: ", depth_lvl + 1);
906                self.print_expr(*in_expr, depth_lvl + 2);
907
908                if let Some(out_expr) = out_expr {
909                    print_indented!(self, "out_expr: Some( ", depth_lvl + 1);
910                    self.print_expr(*out_expr, depth_lvl + 2);
911                    print_indented!(self, ")", depth_lvl + 1);
912                } else {
913                    print_indented!(self, "out_expr: None", depth_lvl + 1);
914                }
915
916                print_indented!(self, "}", depth_lvl + 1);
917            }
918            InlineAsmOperand::Const { value, span } => {
919                print_indented!(self, "InlineAsmOperand::Const {", depth_lvl);
920                print_indented!(self, format!("value: {:?}", value), depth_lvl + 1);
921                print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
922                print_indented!(self, "}", depth_lvl + 1);
923            }
924            InlineAsmOperand::SymFn { value, span } => {
925                print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl);
926                print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1);
927                print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
928                print_indented!(self, "}", depth_lvl + 1);
929            }
930            InlineAsmOperand::SymStatic { def_id } => {
931                print_indented!(self, "InlineAsmOperand::SymStatic {", depth_lvl);
932                print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
933                print_indented!(self, "}", depth_lvl + 1);
934            }
935            InlineAsmOperand::Label { block } => {
936                print_indented!(self, "InlineAsmOperand::Block {", depth_lvl);
937                print_indented!(self, "block:", depth_lvl + 1);
938                self.print_block(*block, depth_lvl + 2);
939                print_indented!(self, "}", depth_lvl + 1);
940            }
941        }
942    }
943}