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