diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index ae3ac8625b186..a7c040397a154 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -498,6 +498,21 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante out } + ThirFlat => { + let mut out = String::new(); + abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess); + debug!("pretty printing THIR flat"); + for did in tcx.hir().body_owners() { + let _ = writeln!( + out, + "{:?}:\n{}\n", + did, + tcx.thir_flat(ty::WithOptConstParam::unknown(did)) + ); + } + out + } + _ => unreachable!(), }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b1e0d380d04bc..2543614318f6d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -361,6 +361,13 @@ rustc_queries! { desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) } } + /// Create a list-like THIR representation for debugging. + query thir_flat(key: ty::WithOptConstParam<LocalDefId>) -> String { + no_hash + arena_cache + desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.did.to_def_id()) } + } + /// Set of all the `DefId`s in this crate that have MIR associated with /// them. This includes all the body owners, but also things like struct /// constructors. diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 5f320708c8416..6f2dac467532c 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -29,6 +29,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use std::fmt; use std::ops::Index; +pub mod print; pub mod visit; macro_rules! thir_with_elements { diff --git a/compiler/rustc_middle/src/thir/print.rs b/compiler/rustc_middle/src/thir/print.rs new file mode 100644 index 0000000000000..60b903e99066b --- /dev/null +++ b/compiler/rustc_middle/src/thir/print.rs @@ -0,0 +1,881 @@ +use crate::thir::*; +use crate::ty::{self, TyCtxt}; + +use std::fmt::{self, Write}; + +impl<'tcx> TyCtxt<'tcx> { + pub fn thir_tree_representation<'a>(self, thir: &'a Thir<'tcx>) -> String { + let mut printer = ThirPrinter::new(thir); + printer.print(); + printer.into_buffer() + } +} + +struct ThirPrinter<'a, 'tcx> { + thir: &'a Thir<'tcx>, + fmt: String, +} + +const INDENT: &str = " "; + +macro_rules! print_indented { + ($writer:ident, $s:expr, $indent_lvl:expr) => { + let indent = (0..$indent_lvl).map(|_| INDENT).collect::<Vec<_>>().concat(); + writeln!($writer, "{}{}", indent, $s).expect("unable to write to ThirPrinter"); + }; +} + +impl<'a, 'tcx> Write for ThirPrinter<'a, 'tcx> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.fmt.push_str(s); + Ok(()) + } +} + +impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { + fn new(thir: &'a Thir<'tcx>) -> Self { + Self { thir, fmt: String::new() } + } + + fn print(&mut self) { + print_indented!(self, "params: [", 0); + for param in self.thir.params.iter() { + self.print_param(param, 1); + } + print_indented!(self, "]", 0); + + print_indented!(self, "body:", 0); + let expr = ExprId::from_usize(self.thir.exprs.len() - 1); + self.print_expr(expr, 1); + } + + fn into_buffer(self) -> String { + self.fmt + } + + fn print_param(&mut self, param: &Param<'tcx>, depth_lvl: usize) { + let Param { pat, ty, ty_span, self_kind, hir_id } = param; + + print_indented!(self, "Param {", depth_lvl); + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1); + print_indented!(self, format!("ty_span: {:?}", ty_span), depth_lvl + 1); + print_indented!(self, format!("self_kind: {:?}", self_kind), depth_lvl + 1); + print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 1); + + if let Some(pat) = pat { + print_indented!(self, "param: Some( ", depth_lvl + 1); + self.print_pat(pat, depth_lvl + 2); + print_indented!(self, ")", depth_lvl + 1); + } else { + print_indented!(self, "param: None", depth_lvl + 1); + } + + print_indented!(self, "}", depth_lvl); + } + + fn print_block(&mut self, block_id: BlockId, depth_lvl: usize) { + let Block { + targeted_by_break, + opt_destruction_scope, + span, + region_scope, + stmts, + expr, + safety_mode, + } = &self.thir.blocks[block_id]; + + print_indented!(self, "Block {", depth_lvl); + print_indented!(self, format!("targeted_by_break: {}", targeted_by_break), depth_lvl + 1); + print_indented!( + self, + format!("opt_destruction_scope: {:?}", opt_destruction_scope), + depth_lvl + 1 + ); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1); + print_indented!(self, format!("safety_mode: {:?}", safety_mode), depth_lvl + 1); + + if stmts.len() > 0 { + print_indented!(self, "stmts: [", depth_lvl + 1); + for stmt in stmts.iter() { + self.print_stmt(*stmt, depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + } else { + print_indented!(self, "stmts: []", depth_lvl + 1); + } + + if let Some(expr_id) = expr { + print_indented!(self, "expr:", depth_lvl + 1); + self.print_expr(*expr_id, depth_lvl + 2); + } else { + print_indented!(self, "expr: []", depth_lvl + 1); + } + + print_indented!(self, "}", depth_lvl); + } + + fn print_stmt(&mut self, stmt_id: StmtId, depth_lvl: usize) { + let Stmt { kind, opt_destruction_scope } = &self.thir.stmts[stmt_id]; + + print_indented!(self, "Stmt {", depth_lvl); + print_indented!( + self, + format!("opt_destruction_scope: {:?}", opt_destruction_scope), + depth_lvl + 1 + ); + + match kind { + StmtKind::Expr { scope, expr } => { + print_indented!(self, "kind: Expr {", depth_lvl + 1); + print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 2); + print_indented!(self, "expr:", depth_lvl + 2); + self.print_expr(*expr, depth_lvl + 3); + print_indented!(self, "}", depth_lvl + 1); + } + StmtKind::Let { + remainder_scope, + init_scope, + pattern, + initializer, + else_block, + lint_level, + } => { + print_indented!(self, "kind: Let {", depth_lvl + 1); + print_indented!( + self, + format!("remainder_scope: {:?}", remainder_scope), + depth_lvl + 2 + ); + print_indented!(self, format!("init_scope: {:?}", init_scope), depth_lvl + 2); + + print_indented!(self, "pattern: ", depth_lvl + 2); + self.print_pat(pattern, depth_lvl + 3); + print_indented!(self, ",", depth_lvl + 2); + + if let Some(init) = initializer { + print_indented!(self, "initializer: Some(", depth_lvl + 2); + self.print_expr(*init, depth_lvl + 3); + print_indented!(self, ")", depth_lvl + 2); + } else { + print_indented!(self, "initializer: None", depth_lvl + 2); + } + + if let Some(else_block) = else_block { + print_indented!(self, "else_block: Some(", depth_lvl + 2); + self.print_block(*else_block, depth_lvl + 3); + print_indented!(self, ")", depth_lvl + 2); + } else { + print_indented!(self, "else_block: None", depth_lvl + 2); + } + + print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + } + + print_indented!(self, "}", depth_lvl); + } + + fn print_expr(&mut self, expr: ExprId, depth_lvl: usize) { + let Expr { ty, temp_lifetime, span, kind } = &self.thir[expr]; + print_indented!(self, "Expr {", depth_lvl); + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1); + print_indented!(self, format!("temp_lifetime: {:?}", temp_lifetime), depth_lvl + 1); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "kind: ", depth_lvl + 1); + self.print_expr_kind(kind, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + + fn print_expr_kind(&mut self, expr_kind: &ExprKind<'tcx>, depth_lvl: usize) { + use rustc_middle::thir::ExprKind::*; + + match expr_kind { + Scope { region_scope, value, lint_level } => { + print_indented!(self, "Scope {", depth_lvl); + print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1); + print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1); + print_indented!(self, "value:", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Box { value } => { + print_indented!(self, "Box {", depth_lvl); + self.print_expr(*value, depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + If { if_then_scope, cond, then, else_opt } => { + print_indented!(self, "If {", depth_lvl); + print_indented!(self, format!("if_then_scope: {:?}", if_then_scope), depth_lvl + 1); + print_indented!(self, "cond:", depth_lvl + 1); + self.print_expr(*cond, depth_lvl + 2); + print_indented!(self, "then:", depth_lvl + 1); + self.print_expr(*then, depth_lvl + 2); + + if let Some(else_expr) = else_opt { + print_indented!(self, "else:", depth_lvl + 1); + self.print_expr(*else_expr, depth_lvl + 2); + } + + print_indented!(self, "}", depth_lvl); + } + Call { fun, args, ty, from_hir_call, fn_span } => { + print_indented!(self, "Call {", depth_lvl); + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1); + print_indented!(self, format!("from_hir_call: {}", from_hir_call), depth_lvl + 1); + print_indented!(self, format!("fn_span: {:?}", fn_span), depth_lvl + 1); + print_indented!(self, "fun:", depth_lvl + 1); + self.print_expr(*fun, depth_lvl + 2); + + if args.len() > 0 { + print_indented!(self, "args: [", depth_lvl + 1); + for arg in args.iter() { + self.print_expr(*arg, depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + } else { + print_indented!(self, "args: []", depth_lvl + 1); + } + + print_indented!(self, "}", depth_lvl); + } + Deref { arg } => { + print_indented!(self, "Deref {", depth_lvl); + self.print_expr(*arg, depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Binary { op, lhs, rhs } => { + print_indented!(self, "Binary {", depth_lvl); + print_indented!(self, format!("op: {:?}", op), depth_lvl + 1); + print_indented!(self, "lhs:", depth_lvl + 1); + self.print_expr(*lhs, depth_lvl + 2); + print_indented!(self, "rhs:", depth_lvl + 1); + self.print_expr(*rhs, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + LogicalOp { op, lhs, rhs } => { + print_indented!(self, "LogicalOp {", depth_lvl); + print_indented!(self, format!("op: {:?}", op), depth_lvl + 1); + print_indented!(self, "lhs:", depth_lvl + 1); + self.print_expr(*lhs, depth_lvl + 2); + print_indented!(self, "rhs:", depth_lvl + 1); + self.print_expr(*rhs, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Unary { op, arg } => { + print_indented!(self, "Unary {", depth_lvl); + print_indented!(self, format!("op: {:?}", op), depth_lvl + 1); + print_indented!(self, "arg:", depth_lvl + 1); + self.print_expr(*arg, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Cast { source } => { + print_indented!(self, "Cast {", depth_lvl); + print_indented!(self, "source:", depth_lvl + 1); + self.print_expr(*source, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Use { source } => { + print_indented!(self, "Use {", depth_lvl); + print_indented!(self, "source:", depth_lvl + 1); + self.print_expr(*source, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + NeverToAny { source } => { + print_indented!(self, "NeverToAny {", depth_lvl); + print_indented!(self, "source:", depth_lvl + 1); + self.print_expr(*source, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Pointer { cast, source } => { + print_indented!(self, "Pointer {", depth_lvl); + print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1); + print_indented!(self, "source:", depth_lvl + 1); + self.print_expr(*source, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Loop { body } => { + print_indented!(self, "Loop (", depth_lvl); + print_indented!(self, "body:", depth_lvl + 1); + self.print_expr(*body, depth_lvl + 2); + print_indented!(self, ")", depth_lvl); + } + Let { expr, pat } => { + print_indented!(self, "Let {", depth_lvl); + print_indented!(self, "expr:", depth_lvl + 1); + self.print_expr(*expr, depth_lvl + 2); + print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Match { scrutinee, arms } => { + print_indented!(self, "Match {", depth_lvl); + print_indented!(self, "scrutinee:", depth_lvl + 1); + self.print_expr(*scrutinee, depth_lvl + 2); + + print_indented!(self, "arms: [", depth_lvl + 1); + for arm_id in arms.iter() { + self.print_arm(*arm_id, depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Block { block } => self.print_block(*block, depth_lvl), + Assign { lhs, rhs } => { + print_indented!(self, "Assign {", depth_lvl); + print_indented!(self, "lhs:", depth_lvl + 1); + self.print_expr(*lhs, depth_lvl + 2); + print_indented!(self, "rhs:", depth_lvl + 1); + self.print_expr(*rhs, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + AssignOp { op, lhs, rhs } => { + print_indented!(self, "AssignOp {", depth_lvl); + print_indented!(self, format!("op: {:?}", op), depth_lvl + 1); + print_indented!(self, "lhs:", depth_lvl + 1); + self.print_expr(*lhs, depth_lvl + 2); + print_indented!(self, "rhs:", depth_lvl + 1); + self.print_expr(*rhs, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Field { lhs, variant_index, name } => { + print_indented!(self, "Field {", depth_lvl); + print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 1); + print_indented!(self, format!("name: {:?}", name), depth_lvl + 1); + print_indented!(self, "lhs:", depth_lvl + 1); + self.print_expr(*lhs, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Index { lhs, index } => { + print_indented!(self, "Index {", depth_lvl); + print_indented!(self, format!("index: {:?}", index), depth_lvl + 1); + print_indented!(self, "lhs:", depth_lvl + 1); + self.print_expr(*lhs, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + VarRef { id } => { + print_indented!(self, "VarRef {", depth_lvl); + print_indented!(self, format!("id: {:?}", id), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + UpvarRef { closure_def_id, var_hir_id } => { + print_indented!(self, "UpvarRef {", depth_lvl); + print_indented!( + self, + format!("closure_def_id: {:?}", closure_def_id), + depth_lvl + 1 + ); + print_indented!(self, format!("var_hir_id: {:?}", var_hir_id), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Borrow { borrow_kind, arg } => { + print_indented!(self, "Borrow (", depth_lvl); + print_indented!(self, format!("borrow_kind: {:?}", borrow_kind), depth_lvl + 1); + print_indented!(self, "arg:", depth_lvl + 1); + self.print_expr(*arg, depth_lvl + 2); + print_indented!(self, ")", depth_lvl); + } + AddressOf { mutability, arg } => { + print_indented!(self, "AddressOf {", depth_lvl); + print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 1); + print_indented!(self, "arg:", depth_lvl + 1); + self.print_expr(*arg, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Break { label, value } => { + print_indented!(self, "Break (", depth_lvl); + print_indented!(self, format!("label: {:?}", label), depth_lvl + 1); + + if let Some(value) = value { + print_indented!(self, "value:", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); + } + + print_indented!(self, ")", depth_lvl); + } + Continue { label } => { + print_indented!(self, "Continue {", depth_lvl); + print_indented!(self, format!("label: {:?}", label), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Return { value } => { + print_indented!(self, "Return {", depth_lvl); + print_indented!(self, "value:", depth_lvl + 1); + + if let Some(value) = value { + self.print_expr(*value, depth_lvl + 2); + } + + print_indented!(self, "}", depth_lvl); + } + ConstBlock { did, substs } => { + print_indented!(self, "ConstBlock {", depth_lvl); + print_indented!(self, format!("did: {:?}", did), depth_lvl + 1); + print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Repeat { value, count } => { + print_indented!(self, "Repeat {", depth_lvl); + print_indented!(self, format!("count: {:?}", count), depth_lvl + 1); + print_indented!(self, "value:", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Array { fields } => { + print_indented!(self, "Array {", depth_lvl); + print_indented!(self, "fields: [", depth_lvl + 1); + for field_id in fields.iter() { + self.print_expr(*field_id, depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Tuple { fields } => { + print_indented!(self, "Tuple {", depth_lvl); + print_indented!(self, "fields: [", depth_lvl + 1); + for field_id in fields.iter() { + self.print_expr(*field_id, depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Adt(adt_expr) => { + print_indented!(self, "Adt {", depth_lvl); + self.print_adt_expr(&**adt_expr, depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + PlaceTypeAscription { source, user_ty } => { + print_indented!(self, "PlaceTypeAscription {", depth_lvl); + print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1); + print_indented!(self, "source:", depth_lvl + 1); + self.print_expr(*source, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + ValueTypeAscription { source, user_ty } => { + print_indented!(self, "ValueTypeAscription {", depth_lvl); + print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1); + print_indented!(self, "source:", depth_lvl + 1); + self.print_expr(*source, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Closure(closure_expr) => { + print_indented!(self, "Closure {", depth_lvl); + print_indented!(self, "closure_expr:", depth_lvl + 1); + self.print_closure_expr(&**closure_expr, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + Literal { lit, neg } => { + print_indented!( + self, + format!("Literal( lit: {:?}, neg: {:?})\n", lit, neg), + depth_lvl + ); + } + NonHirLiteral { lit, user_ty } => { + print_indented!(self, "NonHirLiteral {", depth_lvl); + print_indented!(self, format!("lit: {:?}", lit), depth_lvl + 1); + print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + ZstLiteral { user_ty } => { + print_indented!(self, format!("ZstLiteral(user_ty: {:?})", user_ty), depth_lvl); + } + NamedConst { def_id, substs, user_ty } => { + print_indented!(self, "NamedConst {", depth_lvl); + print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); + print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1); + print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + ConstParam { param, def_id } => { + print_indented!(self, "ConstParam {", depth_lvl); + print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); + print_indented!(self, format!("param: {:?}", param), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + StaticRef { alloc_id, ty, def_id } => { + print_indented!(self, "StaticRef {", depth_lvl); + print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1); + print_indented!(self, format!("alloc_id: {:?}", alloc_id), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + InlineAsm(expr) => { + print_indented!(self, "InlineAsm {", depth_lvl); + print_indented!(self, "expr:", depth_lvl + 1); + self.print_inline_asm_expr(&**expr, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + ThreadLocalRef(def_id) => { + print_indented!(self, "ThreadLocalRef {", depth_lvl); + print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + Yield { value } => { + print_indented!(self, "Yield {", depth_lvl); + print_indented!(self, "value:", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } + } + } + + fn print_adt_expr(&mut self, adt_expr: &AdtExpr<'tcx>, depth_lvl: usize) { + print_indented!(self, "adt_def:", depth_lvl); + self.print_adt_def(adt_expr.adt_def, depth_lvl + 1); + print_indented!( + self, + format!("variant_index: {:?}", adt_expr.variant_index), + depth_lvl + 1 + ); + print_indented!(self, format!("substs: {:?}", adt_expr.substs), depth_lvl + 1); + print_indented!(self, format!("user_ty: {:?}", adt_expr.user_ty), depth_lvl + 1); + + for (i, field_expr) in adt_expr.fields.iter().enumerate() { + print_indented!(self, format!("field {}:", i), depth_lvl + 1); + self.print_expr(field_expr.expr, depth_lvl + 2); + } + + if let Some(ref base) = adt_expr.base { + print_indented!(self, "base:", depth_lvl + 1); + self.print_fru_info(base, depth_lvl + 2); + } else { + print_indented!(self, "base: None", depth_lvl + 1); + } + } + + fn print_adt_def(&mut self, adt_def: ty::AdtDef<'tcx>, depth_lvl: usize) { + print_indented!(self, "AdtDef {", depth_lvl); + print_indented!(self, format!("did: {:?}", adt_def.did()), depth_lvl + 1); + print_indented!(self, format!("variants: {:?}", adt_def.variants()), depth_lvl + 1); + print_indented!(self, format!("flags: {:?}", adt_def.flags()), depth_lvl + 1); + print_indented!(self, format!("repr: {:?}", adt_def.repr()), depth_lvl + 1); + } + + fn print_fru_info(&mut self, fru_info: &FruInfo<'tcx>, depth_lvl: usize) { + print_indented!(self, "FruInfo {", depth_lvl); + print_indented!(self, "base: ", depth_lvl + 1); + self.print_expr(fru_info.base, depth_lvl + 2); + print_indented!(self, "field_types: [", depth_lvl + 1); + for ty in fru_info.field_types.iter() { + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2); + } + print_indented!(self, "}", depth_lvl); + } + + fn print_arm(&mut self, arm_id: ArmId, depth_lvl: usize) { + print_indented!(self, "Arm {", depth_lvl); + + let arm = &self.thir.arms[arm_id]; + let Arm { pattern, guard, body, lint_level, scope, span } = arm; + + print_indented!(self, "pattern: ", depth_lvl + 1); + self.print_pat(pattern, depth_lvl + 2); + + if let Some(guard) = guard { + print_indented!(self, "guard: ", depth_lvl + 1); + self.print_guard(guard, depth_lvl + 2); + } else { + print_indented!(self, "guard: None", depth_lvl + 1); + } + + print_indented!(self, "body: ", depth_lvl + 1); + self.print_expr(*body, depth_lvl + 2); + print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1); + print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 1); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + + fn print_pat(&mut self, pat: &Box<Pat<'tcx>>, depth_lvl: usize) { + let Pat { ty, span, kind } = &**pat; + + print_indented!(self, "Pat: {", depth_lvl); + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + self.print_pat_kind(kind, depth_lvl + 1); + print_indented!(self, "}", depth_lvl); + } + + fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) { + print_indented!(self, "kind: PatKind {", depth_lvl); + + match pat_kind { + PatKind::Wild => { + print_indented!(self, "Wild", depth_lvl + 1); + } + PatKind::AscribeUserType { ascription, subpattern } => { + print_indented!(self, "AscribeUserType: {", depth_lvl + 1); + print_indented!(self, format!("ascription: {:?}", ascription), depth_lvl + 2); + print_indented!(self, "subpattern: ", depth_lvl + 2); + self.print_pat(subpattern, depth_lvl + 3); + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Binding { mutability, name, mode, var, ty, subpattern, is_primary } => { + print_indented!(self, "Binding {", depth_lvl + 1); + print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 2); + print_indented!(self, format!("name: {:?}", name), depth_lvl + 2); + print_indented!(self, format!("mode: {:?}", mode), depth_lvl + 2); + print_indented!(self, format!("var: {:?}", var), depth_lvl + 2); + print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2); + print_indented!(self, format!("is_primary: {:?}", is_primary), depth_lvl + 2); + + if let Some(subpattern) = subpattern { + print_indented!(self, "subpattern: Some( ", depth_lvl + 2); + self.print_pat(subpattern, depth_lvl + 3); + print_indented!(self, ")", depth_lvl + 2); + } else { + print_indented!(self, "subpattern: None", depth_lvl + 2); + } + + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Variant { adt_def, substs, variant_index, subpatterns } => { + print_indented!(self, "Variant {", depth_lvl + 1); + print_indented!(self, "adt_def: ", depth_lvl + 2); + self.print_adt_def(*adt_def, depth_lvl + 3); + print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 2); + print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 2); + + if subpatterns.len() > 0 { + print_indented!(self, "subpatterns: [", depth_lvl + 2); + for field_pat in subpatterns.iter() { + self.print_pat(&field_pat.pattern, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + } else { + print_indented!(self, "subpatterns: []", depth_lvl + 2); + } + + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Leaf { subpatterns } => { + print_indented!(self, "Leaf { ", depth_lvl + 1); + print_indented!(self, "subpatterns: [", depth_lvl + 2); + for field_pat in subpatterns.iter() { + self.print_pat(&field_pat.pattern, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Deref { subpattern } => { + print_indented!(self, "Deref { ", depth_lvl + 1); + print_indented!(self, "subpattern: ", depth_lvl + 2); + self.print_pat(subpattern, depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Constant { value } => { + print_indented!(self, "Constant {", depth_lvl + 1); + print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Range(pat_range) => { + print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1); + } + PatKind::Slice { prefix, slice, suffix } => { + print_indented!(self, "Slice {", depth_lvl + 1); + + print_indented!(self, "prefix: [", depth_lvl + 2); + for prefix_pat in prefix.iter() { + self.print_pat(prefix_pat, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + + if let Some(slice) = slice { + print_indented!(self, "slice: ", depth_lvl + 2); + self.print_pat(slice, depth_lvl + 3); + } + + print_indented!(self, "suffix: [", depth_lvl + 2); + for suffix_pat in suffix.iter() { + self.print_pat(suffix_pat, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Array { prefix, slice, suffix } => { + print_indented!(self, "Array {", depth_lvl + 1); + + print_indented!(self, "prefix: [", depth_lvl + 2); + for prefix_pat in prefix.iter() { + self.print_pat(prefix_pat, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + + if let Some(slice) = slice { + print_indented!(self, "slice: ", depth_lvl + 2); + self.print_pat(slice, depth_lvl + 3); + } + + print_indented!(self, "suffix: [", depth_lvl + 2); + for suffix_pat in suffix.iter() { + self.print_pat(suffix_pat, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + + print_indented!(self, "}", depth_lvl + 1); + } + PatKind::Or { pats } => { + print_indented!(self, "Or {", depth_lvl + 1); + print_indented!(self, "pats: [", depth_lvl + 2); + for pat in pats.iter() { + self.print_pat(pat, depth_lvl + 3); + } + print_indented!(self, "]", depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + } + + print_indented!(self, "}", depth_lvl); + } + + fn print_guard(&mut self, guard: &Guard<'tcx>, depth_lvl: usize) { + print_indented!(self, "Guard {", depth_lvl); + + match guard { + Guard::If(expr_id) => { + print_indented!(self, "If (", depth_lvl + 1); + self.print_expr(*expr_id, depth_lvl + 2); + print_indented!(self, ")", depth_lvl + 1); + } + Guard::IfLet(pat, expr_id) => { + print_indented!(self, "IfLet (", depth_lvl + 1); + self.print_pat(pat, depth_lvl + 2); + print_indented!(self, ",", depth_lvl + 1); + self.print_expr(*expr_id, depth_lvl + 2); + print_indented!(self, ")", depth_lvl + 1); + } + } + + print_indented!(self, "}", depth_lvl); + } + + fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) { + let ClosureExpr { closure_id, substs, upvars, movability, fake_reads } = expr; + + print_indented!(self, "ClosureExpr {", depth_lvl); + print_indented!(self, format!("closure_id: {:?}", closure_id), depth_lvl + 1); + print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1); + + if upvars.len() > 0 { + print_indented!(self, "upvars: [", depth_lvl + 1); + for upvar in upvars.iter() { + self.print_expr(*upvar, depth_lvl + 2); + print_indented!(self, ",", depth_lvl + 1); + } + print_indented!(self, "]", depth_lvl + 1); + } else { + print_indented!(self, "upvars: []", depth_lvl + 1); + } + + print_indented!(self, format!("movability: {:?}", movability), depth_lvl + 1); + + if fake_reads.len() > 0 { + print_indented!(self, "fake_reads: [", depth_lvl + 1); + for (fake_read_expr, cause, hir_id) in fake_reads.iter() { + print_indented!(self, "(", depth_lvl + 2); + self.print_expr(*fake_read_expr, depth_lvl + 3); + print_indented!(self, ",", depth_lvl + 2); + print_indented!(self, format!("cause: {:?}", cause), depth_lvl + 3); + print_indented!(self, ",", depth_lvl + 2); + print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 3); + print_indented!(self, "),", depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + } else { + print_indented!(self, "fake_reads: []", depth_lvl + 1); + } + + print_indented!(self, "}", depth_lvl); + } + + fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) { + let InlineAsmExpr { template, operands, options, line_spans } = expr; + + print_indented!(self, "InlineAsmExpr {", depth_lvl); + + print_indented!(self, "template: [", depth_lvl + 1); + for template_piece in template.iter() { + print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + + print_indented!(self, "operands: [", depth_lvl + 1); + for operand in operands.iter() { + self.print_inline_operand(operand, depth_lvl + 2); + } + print_indented!(self, "]", depth_lvl + 1); + + print_indented!(self, format!("options: {:?}", options), depth_lvl + 1); + print_indented!(self, format!("line_spans: {:?}", line_spans), depth_lvl + 1); + } + + fn print_inline_operand(&mut self, operand: &InlineAsmOperand<'tcx>, depth_lvl: usize) { + match operand { + InlineAsmOperand::In { reg, expr } => { + print_indented!(self, "InlineAsmOperand::In {", depth_lvl); + print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1); + print_indented!(self, "expr: ", depth_lvl + 1); + self.print_expr(*expr, depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + InlineAsmOperand::Out { reg, late, expr } => { + print_indented!(self, "InlineAsmOperand::Out {", depth_lvl); + print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1); + print_indented!(self, format!("late: {:?}", late), depth_lvl + 1); + + if let Some(out) = expr { + print_indented!(self, "place: Some( ", depth_lvl + 1); + self.print_expr(*out, depth_lvl + 2); + print_indented!(self, ")", depth_lvl + 1); + } else { + print_indented!(self, "place: None", depth_lvl + 1); + } + print_indented!(self, "}", depth_lvl + 1); + } + InlineAsmOperand::InOut { reg, late, expr } => { + print_indented!(self, "InlineAsmOperand::InOut {", depth_lvl); + print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1); + print_indented!(self, format!("late: {:?}", late), depth_lvl + 1); + print_indented!(self, "expr: ", depth_lvl + 1); + self.print_expr(*expr, depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } + InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { + print_indented!(self, "InlineAsmOperand::SplitInOut {", depth_lvl); + print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1); + print_indented!(self, format!("late: {:?}", late), depth_lvl + 1); + print_indented!(self, "in_expr: ", depth_lvl + 1); + self.print_expr(*in_expr, depth_lvl + 2); + + if let Some(out_expr) = out_expr { + print_indented!(self, "out_expr: Some( ", depth_lvl + 1); + self.print_expr(*out_expr, depth_lvl + 2); + print_indented!(self, ")", depth_lvl + 1); + } else { + print_indented!(self, "out_expr: None", depth_lvl + 1); + } + + print_indented!(self, "}", depth_lvl + 1); + } + InlineAsmOperand::Const { value, span } => { + print_indented!(self, "InlineAsmOperand::Const {", depth_lvl); + print_indented!(self, format!("value: {:?}", value), depth_lvl + 1); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "}", depth_lvl + 1); + } + InlineAsmOperand::SymFn { value, span } => { + print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl); + print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "}", depth_lvl + 1); + } + InlineAsmOperand::SymStatic { def_id } => { + print_indented!(self, "InlineAsmOperand::SymStatic {", depth_lvl); + print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); + print_indented!(self, "}", depth_lvl + 1); + } + } + } +} diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9daf68a15f4b1..76d537946044c 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -439,6 +439,10 @@ fn construct_fn<'tcx>( let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did); let generator_kind = tcx.generator_kind(fn_def.did); + // The representation of thir for `-Zunpretty=thir-tree` relies on + // the entry expression being the last element of `thir.exprs`. + assert_eq!(expr.as_usize(), thir.exprs.len() - 1); + // Figure out what primary body this item has. let body_id = tcx.hir().body_owned_by(fn_def.did); let span_with_body = tcx.hir().span_with_body(fn_id); diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a428180a4fa82..94dae36154c26 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -34,4 +34,5 @@ pub fn provide(providers: &mut Providers) { providers.thir_check_unsafety_for_const_arg = check_unsafety::thir_check_unsafety_for_const_arg; providers.thir_body = thir::cx::thir_body; providers.thir_tree = thir::cx::thir_tree; + providers.thir_flat = thir::cx::thir_flat; } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index a355e1bdab5f5..10df4b229520f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -53,6 +53,16 @@ pub(crate) fn thir_body( } pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String { + match thir_body(tcx, owner_def) { + Ok((thir, _)) => { + let thir = thir.steal(); + tcx.thir_tree_representation(&thir) + } + Err(_) => "error".into(), + } +} + +pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String { match thir_body(tcx, owner_def) { Ok((thir, _)) => format!("{:#?}", thir.steal()), Err(_) => "error".into(), diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 586454f76574c..1abe5d242497b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2577,6 +2577,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio "hir,typed" => Hir(PpHirMode::Typed), "hir-tree" => HirTree, "thir-tree" => ThirTree, + "thir-flat" => ThirFlat, "mir" => Mir, "mir-cfg" => MirCFG, name => early_error( @@ -2585,7 +2586,8 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio "argument to `unpretty` must be one of `normal`, `identified`, \ `expanded`, `expanded,identified`, `expanded,hygiene`, \ `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \ - `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {name}" + `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \ + `mir-cfg`; got {name}" ), ), }; @@ -2740,6 +2742,8 @@ pub enum PpMode { HirTree, /// `-Zunpretty=thir-tree` ThirTree, + /// `-Zunpretty=`thir-flat` + ThirFlat, /// `-Zunpretty=mir` Mir, /// `-Zunpretty=mir-cfg` @@ -2758,6 +2762,7 @@ impl PpMode { | Hir(_) | HirTree | ThirTree + | ThirFlat | Mir | MirCFG => true, } @@ -2767,13 +2772,13 @@ impl PpMode { match *self { Source(_) | AstTree(_) => false, - Hir(_) | HirTree | ThirTree | Mir | MirCFG => true, + Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG => true, } } pub fn needs_analysis(&self) -> bool { use PpMode::*; - matches!(*self, Mir | MirCFG | ThirTree) + matches!(*self, Mir | MirCFG | ThirTree | ThirFlat) } } diff --git a/tests/ui/thir-print/thir-flat.rs b/tests/ui/thir-print/thir-flat.rs new file mode 100644 index 0000000000000..8fa95ce62b5ef --- /dev/null +++ b/tests/ui/thir-print/thir-flat.rs @@ -0,0 +1,4 @@ +// compile-flags: -Z unpretty=thir-flat +// check-pass + +pub fn main() {} diff --git a/tests/ui/thir-tree.stdout b/tests/ui/thir-print/thir-flat.stdout similarity index 77% rename from tests/ui/thir-tree.stdout rename to tests/ui/thir-print/thir-flat.stdout index 4b6915f771526..c399fa66b6a03 100644 --- a/tests/ui/thir-tree.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -1,4 +1,4 @@ -DefId(0:3 ~ thir_tree[8f1d]::main): +DefId(0:3 ~ thir_flat[45a6]::main): Thir { arms: [], blocks: [ @@ -6,7 +6,7 @@ Thir { targeted_by_break: false, region_scope: Node(1), opt_destruction_scope: None, - span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + span: $DIR/thir-flat.rs:4:15: 4:17 (#0), stmts: [], expr: None, safety_mode: Safe, @@ -18,7 +18,7 @@ Thir { temp_lifetime: Some( Node(2), ), - span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + span: $DIR/thir-flat.rs:4:15: 4:17 (#0), kind: Block { block: b0, }, @@ -28,11 +28,11 @@ Thir { temp_lifetime: Some( Node(2), ), - span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + span: $DIR/thir-flat.rs:4:15: 4:17 (#0), kind: Scope { region_scope: Node(2), lint_level: Explicit( - HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2), + HirId(DefId(0:3 ~ thir_flat[45a6]::main).2), ), value: e0, }, @@ -42,7 +42,7 @@ Thir { temp_lifetime: Some( Node(2), ), - span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + span: $DIR/thir-flat.rs:4:15: 4:17 (#0), kind: Scope { region_scope: Destruction(2), lint_level: Inherited, diff --git a/tests/ui/thir-print/thir-tree-match.rs b/tests/ui/thir-print/thir-tree-match.rs new file mode 100644 index 0000000000000..a5511ec95437f --- /dev/null +++ b/tests/ui/thir-print/thir-tree-match.rs @@ -0,0 +1,23 @@ +// check-pass +// compile-flags: -Zunpretty=thir-tree + +enum Bar { + First, + Second, + Third, +} + +enum Foo { + FooOne(Bar), + FooTwo, +} + +fn has_match(foo: Foo) -> bool { + match foo { + Foo::FooOne(Bar::First) => true, + Foo::FooOne(_) => false, + Foo::FooTwo => true, + } +} + +fn main() {} diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout new file mode 100644 index 0000000000000..d6174ec262a44 --- /dev/null +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -0,0 +1,342 @@ +DefId(0:16 ~ thir_tree_match[3c9a]::has_match): +params: [ + Param { + ty: Foo + ty_span: Some($DIR/thir-tree-match.rs:15:19: 15:22 (#0)) + self_kind: None + hir_id: Some(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).1)) + param: Some( + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:15:14: 15:17 (#0) + kind: PatKind { + Binding { + mutability: Not + name: "foo" + mode: ByValue + var: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).2)) + ty: Foo + is_primary: true + subpattern: None + } + } + } + ) + } +] +body: + Expr { + ty: bool + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) + kind: + Scope { + region_scope: Destruction(26) + lint_level: Inherited + value: + Expr { + ty: bool + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) + kind: + Scope { + region_scope: Node(26) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).26)) + value: + Expr { + ty: bool + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) + kind: + Block { + targeted_by_break: false + opt_destruction_scope: None + span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) + region_scope: Node(25) + safety_mode: Safe + stmts: [] + expr: + Expr { + ty: bool + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) + kind: + Scope { + region_scope: Node(3) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).3)) + value: + Expr { + ty: bool + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) + kind: + Match { + scrutinee: + Expr { + ty: Foo + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) + kind: + Scope { + region_scope: Node(4) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).4)) + value: + Expr { + ty: Foo + temp_lifetime: Some(Node(26)) + span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).2)) + } + } + } + } + arms: [ + Arm { + pattern: + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:17:9: 17:32 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 } + substs: [] + variant_index: 0 + subpatterns: [ + Pat: { + ty: Bar + span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:3 ~ thir_tree_match[3c9a]::Bar) + variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[3c9a]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[3c9a]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[3c9a]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[3c9a]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[3c9a]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[3c9a]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3125160937860410723 } + substs: [] + variant_index: 0 + subpatterns: [] + } + } + } + ] + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: Some(Node(13)) + span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) + kind: + Scope { + region_scope: Destruction(13) + lint_level: Inherited + value: + Expr { + ty: bool + temp_lifetime: Some(Node(13)) + span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) + kind: + Scope { + region_scope: Node(13) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).13)) + value: + Expr { + ty: bool + temp_lifetime: Some(Node(13)) + span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) + kind: + Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false) + + } + } + } + } + } + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).12)) + scope: Node(12) + span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) + } + Arm { + pattern: + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:18:9: 18:23 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 } + substs: [] + variant_index: 0 + subpatterns: [ + Pat: { + ty: Bar + span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0) + kind: PatKind { + Wild + } + } + ] + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: Some(Node(19)) + span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) + kind: + Scope { + region_scope: Destruction(19) + lint_level: Inherited + value: + Expr { + ty: bool + temp_lifetime: Some(Node(19)) + span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) + kind: + Scope { + region_scope: Node(19) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).19)) + value: + Expr { + ty: bool + temp_lifetime: Some(Node(19)) + span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) + kind: + Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false) + + } + } + } + } + } + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).18)) + scope: Node(18) + span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) + } + Arm { + pattern: + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:19:9: 19:20 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 } + substs: [] + variant_index: 1 + subpatterns: [] + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: Some(Node(24)) + span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) + kind: + Scope { + region_scope: Destruction(24) + lint_level: Inherited + value: + Expr { + ty: bool + temp_lifetime: Some(Node(24)) + span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) + kind: + Scope { + region_scope: Node(24) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).24)) + value: + Expr { + ty: bool + temp_lifetime: Some(Node(24)) + span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) + kind: + Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false) + + } + } + } + } + } + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).23)) + scope: Node(23) + span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) + } + ] + } + } + } + } + } + } + } + } + } + } + + +DefId(0:17 ~ thir_tree_match[3c9a]::main): +params: [ +] +body: + Expr { + ty: () + temp_lifetime: Some(Node(2)) + span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) + kind: + Scope { + region_scope: Destruction(2) + lint_level: Inherited + value: + Expr { + ty: () + temp_lifetime: Some(Node(2)) + span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) + kind: + Scope { + region_scope: Node(2) + lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[3c9a]::main).2)) + value: + Expr { + ty: () + temp_lifetime: Some(Node(2)) + span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) + kind: + Block { + targeted_by_break: false + opt_destruction_scope: None + span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) + region_scope: Node(1) + safety_mode: Safe + stmts: [] + expr: [] + } + } + } + } + } + } + + diff --git a/tests/ui/thir-tree.rs b/tests/ui/thir-print/thir-tree.rs similarity index 100% rename from tests/ui/thir-tree.rs rename to tests/ui/thir-print/thir-tree.rs diff --git a/tests/ui/thir-print/thir-tree.stdout b/tests/ui/thir-print/thir-tree.stdout new file mode 100644 index 0000000000000..0a35d9fb78ca2 --- /dev/null +++ b/tests/ui/thir-print/thir-tree.stdout @@ -0,0 +1,43 @@ +DefId(0:3 ~ thir_tree[8f1d]::main): +params: [ +] +body: + Expr { + ty: () + temp_lifetime: Some(Node(2)) + span: $DIR/thir-tree.rs:4:15: 4:17 (#0) + kind: + Scope { + region_scope: Destruction(2) + lint_level: Inherited + value: + Expr { + ty: () + temp_lifetime: Some(Node(2)) + span: $DIR/thir-tree.rs:4:15: 4:17 (#0) + kind: + Scope { + region_scope: Node(2) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2)) + value: + Expr { + ty: () + temp_lifetime: Some(Node(2)) + span: $DIR/thir-tree.rs:4:15: 4:17 (#0) + kind: + Block { + targeted_by_break: false + opt_destruction_scope: None + span: $DIR/thir-tree.rs:4:15: 4:17 (#0) + region_scope: Node(1) + safety_mode: Safe + stmts: [] + expr: [] + } + } + } + } + } + } + +