From dc3eabd48700863075bd986a497fbe4f227aa33b Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 3 Apr 2021 19:58:46 +0200 Subject: [PATCH 1/2] Store THIR in `IndexVec`s instead of an `Arena` --- compiler/rustc_driver/src/pretty.rs | 16 +- compiler/rustc_mir_build/src/build/block.rs | 33 +- .../src/build/expr/as_constant.rs | 6 +- .../src/build/expr/as_operand.rs | 19 +- .../src/build/expr/as_place.rs | 40 +- .../src/build/expr/as_rvalue.rs | 47 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 6 +- .../src/build/expr/category.rs | 2 +- .../rustc_mir_build/src/build/expr/into.rs | 84 ++-- .../rustc_mir_build/src/build/expr/stmt.rs | 34 +- .../rustc_mir_build/src/build/matches/mod.rs | 35 +- compiler/rustc_mir_build/src/build/mod.rs | 79 +++- compiler/rustc_mir_build/src/build/scope.rs | 4 +- compiler/rustc_mir_build/src/thir/arena.rs | 98 ---- compiler/rustc_mir_build/src/thir/cx/block.rs | 125 ++--- compiler/rustc_mir_build/src/thir/cx/expr.rs | 443 +++++++++--------- compiler/rustc_mir_build/src/thir/cx/mod.rs | 26 +- compiler/rustc_mir_build/src/thir/mod.rs | 212 +++++---- 18 files changed, 681 insertions(+), 628 deletions(-) delete mode 100644 compiler/rustc_mir_build/src/thir/arena.rs diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index e0c140b143be8..a8b6a16ed12f4 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -9,14 +9,12 @@ use rustc_hir_pretty as pprust_hir; use rustc_middle::hir::map as hir_map; use rustc_middle::ty::{self, TyCtxt}; use rustc_mir::util::{write_mir_graphviz, write_mir_pretty}; -use rustc_mir_build::thir; use rustc_session::config::{Input, PpAstTreeMode, PpHirMode, PpMode, PpSourceMode}; use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::FileName; use std::cell::Cell; -use std::fmt::Write; use std::path::Path; pub use self::PpMode::*; @@ -491,18 +489,8 @@ fn print_with_analysis( } ThirTree => { - let mut out = String::new(); - abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess); - debug!("pretty printing THIR tree"); - for did in tcx.body_owners() { - let hir = tcx.hir(); - let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did))); - let arena = thir::Arena::default(); - let thir = - thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value); - let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir); - } - out + // FIXME(rust-lang/project-thir-unsafeck#8) + todo!() } _ => unreachable!(), diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 808c6e3ff644b..ea3a5174fd8bb 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -12,18 +12,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, destination: Place<'tcx>, block: BasicBlock, - ast_block: &Block<'_, 'tcx>, + ast_block: &Block, source_info: SourceInfo, ) -> BlockAnd<()> { let Block { region_scope, opt_destruction_scope, span, - stmts, + ref stmts, expr, targeted_by_break, safety_mode, } = *ast_block; + let expr = expr.map(|expr| &self.thir[expr]); self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| { this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { if targeted_by_break { @@ -32,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, block, span, - stmts, + &stmts, expr, safety_mode, )) }) } else { - this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode) + this.ast_block_stmts(destination, block, span, &stmts, expr, safety_mode) } }) }) @@ -49,8 +50,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, mut block: BasicBlock, span: Span, - stmts: &[Stmt<'_, 'tcx>], - expr: Option<&Expr<'_, 'tcx>>, + stmts: &[StmtId], + expr: Option<&Expr<'tcx>>, safety_mode: BlockSafety, ) -> BlockAnd<()> { let this = self; @@ -78,23 +79,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); - for Stmt { kind, opt_destruction_scope } in stmts { + for stmt in stmts { + let Stmt { ref kind, opt_destruction_scope } = this.thir[*stmt]; match kind { - &StmtKind::Expr { scope, expr } => { + StmtKind::Expr { scope, expr } => { this.block_context.push(BlockFrame::Statement { ignores_expr_result: true }); unpack!( block = this.in_opt_scope( opt_destruction_scope.map(|de| (de, source_info)), |this| { - let si = (scope, source_info); + let si = (*scope, source_info); this.in_scope(si, LintLevel::Inherited, |this| { - this.stmt_expr(block, expr, Some(scope)) + this.stmt_expr(block, &this.thir[*expr], Some(*scope)) }) } ) ); } - StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => { + StmtKind::Let { + remainder_scope, + init_scope, + ref pattern, + initializer, + lint_level, + } => { let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild); this.block_context.push(BlockFrame::Statement { ignores_expr_result }); @@ -110,6 +118,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { + let init = &this.thir[*init]; let initializer_span = init.span; unpack!( @@ -145,7 +154,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("ast_block_stmts: pattern={:?}", pattern); this.visit_primary_bindings( - &pattern, + pattern, UserTypeProjections::none(), &mut |this, _, _, _, node, span, _, _| { this.storage_live_binding(block, node, span, OutsideGuard, true); diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 57f56e2d09227..796a90713ba07 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -8,11 +8,13 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! - crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> { + crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { let this = self; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; match *kind { - ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value), + ExprKind::Scope { region_scope: _, lint_level: _, value } => { + this.as_constant(&this.thir[value]) + } ExprKind::Literal { literal, user_ty, const_id: _ } => { let user_ty = user_ty.map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index c393878e0b995..1c439aad39497 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -17,7 +17,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_local_operand( &mut self, block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_operand(block, Some(local_scope), expr) @@ -74,7 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_local_call_operand( &mut self, block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_call_operand(block, Some(local_scope), expr) @@ -93,7 +93,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, scope: Option, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { debug!("as_operand(block={:?}, expr={:?})", block, expr); let this = self; @@ -101,8 +101,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); - return this - .in_scope(region_scope, lint_level, |this| this.as_operand(block, scope, value)); + return this.in_scope(region_scope, lint_level, |this| { + this.as_operand(block, scope, &this.thir[value]) + }); } let category = Category::of(&expr.kind).unwrap(); @@ -123,7 +124,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, scope: Option, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { debug!("as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; @@ -132,7 +133,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { - this.as_call_operand(block, scope, value) + this.as_call_operand(block, scope, &this.thir[value]) }); } @@ -151,7 +152,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // type, and that value is coming from the deref of a box. if let ExprKind::Deref { arg } = expr.kind { // Generate let tmp0 = arg0 - let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); + let operand = unpack!( + block = this.as_temp(block, scope, &this.thir[arg], Mutability::Mut) + ); // Return the operand *tmp0 to be used as the call argument let place = Place { diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 1053890e61837..96df77a65da9e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -381,7 +381,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_place( &mut self, mut block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { let place_builder = unpack!(block = self.as_place_builder(block, expr)); block.and(place_builder.into_place(self.tcx, self.typeck_results)) @@ -392,7 +392,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_place_builder( &mut self, block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { self.expr_as_place(block, expr, Mutability::Mut, None) } @@ -405,7 +405,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_read_only_place( &mut self, mut block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); block.and(place_builder.into_place(self.tcx, self.typeck_results)) @@ -420,7 +420,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn as_read_only_place_builder( &mut self, block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { self.expr_as_place(block, expr, Mutability::Not, None) } @@ -428,7 +428,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn expr_as_place( &mut self, mut block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, ) -> BlockAnd> { @@ -440,23 +440,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { this.in_scope((region_scope, source_info), lint_level, |this| { - this.expr_as_place(block, value, mutability, fake_borrow_temps) + this.expr_as_place(block, &this.thir[value], mutability, fake_borrow_temps) }) } ExprKind::Field { lhs, name } => { - let place_builder = - unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,)); + let place_builder = unpack!( + block = + this.expr_as_place(block, &this.thir[lhs], mutability, fake_borrow_temps,) + ); block.and(place_builder.field(name, expr.ty)) } ExprKind::Deref { arg } => { - let place_builder = - unpack!(block = this.expr_as_place(block, arg, mutability, fake_borrow_temps,)); + let place_builder = unpack!( + block = + this.expr_as_place(block, &this.thir[arg], mutability, fake_borrow_temps,) + ); block.and(place_builder.deref()) } ExprKind::Index { lhs, index } => this.lower_index_expression( block, - lhs, - index, + &this.thir[lhs], + &this.thir[index], mutability, fake_borrow_temps, expr.temp_lifetime, @@ -481,7 +485,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::PlaceTypeAscription { source, user_ty } => { let place_builder = unpack!( - block = this.expr_as_place(block, source, mutability, fake_borrow_temps,) + block = this.expr_as_place( + block, + &this.thir[source], + mutability, + fake_borrow_temps, + ) ); if let Some(user_ty) = user_ty { let annotation_index = @@ -509,6 +518,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(place_builder) } ExprKind::ValueTypeAscription { source, user_ty } => { + let source = &this.thir[source]; let temp = unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability)); if let Some(user_ty) = user_ty { @@ -613,8 +623,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_index_expression( &mut self, mut block: BasicBlock, - base: &Expr<'_, 'tcx>, - index: &Expr<'_, 'tcx>, + base: &Expr<'tcx>, + index: &Expr<'tcx>, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, temp_lifetime: Option, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 822fbd91c947e..92a2a7bc17a8b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -23,7 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_local_rvalue( &mut self, block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_rvalue(block, Some(local_scope), expr) @@ -34,7 +34,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, scope: Option, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr); @@ -46,19 +46,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)), ExprKind::Scope { region_scope, lint_level, value } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value)) + this.in_scope(region_scope, lint_level, |this| { + this.as_rvalue(block, scope, &this.thir[value]) + }) } ExprKind::Repeat { value, count } => { - let value_operand = unpack!(block = this.as_operand(block, scope, value)); + let value_operand = + unpack!(block = this.as_operand(block, scope, &this.thir[value])); block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Binary { op, lhs, rhs } => { - let lhs = unpack!(block = this.as_operand(block, scope, lhs)); - let rhs = unpack!(block = this.as_operand(block, scope, rhs)); + let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs])); + let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs])); this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { - let arg = unpack!(block = this.as_operand(block, scope, arg)); + let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg])); // Check for -MIN on signed integers if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() { let bool_ty = this.tcx.types.bool; @@ -84,6 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::UnaryOp(op, arg)) } ExprKind::Box { value } => { + let value = &this.thir[value]; // The `Box` temporary created here is not a part of the HIR, // and therefore is not considered during generator auto-trait // determination. See the comment about `box` at `yield_in_scope`. @@ -112,14 +116,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::Use(Operand::Move(Place::from(result)))) } ExprKind::Cast { source } => { - let source = unpack!(block = this.as_operand(block, scope, source)); + let source = unpack!(block = this.as_operand(block, scope, &this.thir[source])); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } ExprKind::Pointer { cast, source } => { - let source = unpack!(block = this.as_operand(block, scope, source)); + let source = unpack!(block = this.as_operand(block, scope, &this.thir[source])); block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) } - ExprKind::Array { fields } => { + ExprKind::Array { ref fields } => { // (*) We would (maybe) be closer to codegen if we // handled this and other aggregate cases via // `into()`, not `as_rvalue` -- in that case, instead @@ -150,22 +154,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let el_ty = expr.ty.sequence_element_type(this.tcx); let fields: Vec<_> = fields .into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, f))) + .copied() + .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f]))) .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields)) } - ExprKind::Tuple { fields } => { + ExprKind::Tuple { ref fields } => { // see (*) above // first process the set of fields let fields: Vec<_> = fields .into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, f))) + .copied() + .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f]))) .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields)) } - ExprKind::Closure { closure_id, substs, upvars, movability, ref fake_reads } => { + ExprKind::Closure { closure_id, substs, ref upvars, movability, ref fake_reads } => { // Convert the closure fake reads, if any, from `ExprRef` to mir `Place` // and push the fake reads. // This must come before creating the operands. This is required in case @@ -180,7 +186,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // }; // ``` for (thir_place, cause, hir_id) in fake_reads.into_iter() { - let place_builder = unpack!(block = this.as_place_builder(block, thir_place)); + let place_builder = + unpack!(block = this.as_place_builder(block, &this.thir[*thir_place])); if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this.tcx, this.typeck_results) @@ -199,7 +206,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // see (*) above let operands: Vec<_> = upvars .into_iter() + .copied() .map(|upvar| { + let upvar = &this.thir[upvar]; match Category::of(&upvar.kind) { // Use as_place to avoid creating a temporary when // moving a variable into a closure, so that @@ -225,7 +234,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arg, } => unpack!( block = this.limit_capture_mutability( - upvar.span, upvar.ty, scope, block, arg, + upvar.span, + upvar.ty, + scope, + block, + &this.thir[arg], ) ), _ => unpack!(block = this.as_operand(block, scope, upvar)), @@ -398,7 +411,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { upvar_ty: Ty<'tcx>, temp_lifetime: Option, mut block: BasicBlock, - arg: &Expr<'_, 'tcx>, + arg: &Expr<'tcx>, ) -> BlockAnd> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 98b910ab21c16..96bf3e6d69d6d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -14,7 +14,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, block: BasicBlock, temp_lifetime: Option, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, mutability: Mutability, ) -> BlockAnd { // this is the only place in mir building that we need to truly need to worry about @@ -27,7 +27,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, temp_lifetime: Option, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, mutability: Mutability, ) -> BlockAnd { debug!( @@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr_span); if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { return this.in_scope((region_scope, source_info), lint_level, |this| { - this.as_temp(block, temp_lifetime, value, mutability) + this.as_temp(block, temp_lifetime, &this.thir[value], mutability) }); } diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index 0cadfa2f0a1af..9320b5810e396 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -31,7 +31,7 @@ crate enum RvalueFunc { /// Determines the category for a given expression. Note that scope /// and paren expressions have no category. impl Category { - crate fn of(ek: &ExprKind<'_, '_>) -> Option { + crate fn of(ek: &ExprKind<'_>) -> Option { match *ek { ExprKind::Scope { .. } => None, diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 1e7ed3d95d236..d7c8a07103e3c 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -19,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, destination: Place<'tcx>, mut block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd<()> { debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr); @@ -42,19 +42,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let region_scope = (region_scope, source_info); ensure_sufficient_stack(|| { this.in_scope(region_scope, lint_level, |this| { - this.expr_into_dest(destination, block, value) + this.expr_into_dest(destination, block, &this.thir[value]) }) }) } ExprKind::Block { body: ref ast_block } => { this.ast_block(destination, block, ast_block, source_info) } - ExprKind::Match { scrutinee, arms } => { - this.match_expr(destination, expr_span, block, scrutinee, arms) + ExprKind::Match { scrutinee, ref arms } => { + this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms) } ExprKind::If { cond, then, else_opt } => { let place = unpack!( - block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut) + block = this.as_temp( + block, + Some(this.local_scope()), + &this.thir[cond], + Mutability::Mut + ) ); let operand = Operand::Move(Place::from(place)); @@ -63,9 +68,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block); this.cfg.terminate(block, source_info, term); - unpack!(then_block = this.expr_into_dest(destination, then_block, then)); + unpack!( + then_block = this.expr_into_dest(destination, then_block, &this.thir[then]) + ); else_block = if let Some(else_opt) = else_opt { - unpack!(this.expr_into_dest(destination, else_block, else_opt)) + unpack!(this.expr_into_dest(destination, else_block, &this.thir[else_opt])) } else { // Body of the `if` expression without an `else` clause must return `()`, thus // we implicitly generate a `else {}` if it is not specified. @@ -89,6 +96,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { join_block.unit() } ExprKind::NeverToAny { source } => { + let source = &this.thir[source]; let is_call = matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. }); @@ -127,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.start_new_block(), ); - let lhs = unpack!(block = this.as_local_operand(block, lhs)); + let lhs = unpack!(block = this.as_local_operand(block, &this.thir[lhs])); let blocks = match op { LogicalOp::And => (else_block, shortcircuit_block), LogicalOp::Or => (shortcircuit_block, else_block), @@ -150,7 +158,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); this.cfg.goto(shortcircuit_block, source_info, join_block); - let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); + let rhs = unpack!(else_block = this.as_local_operand(else_block, &this.thir[rhs])); this.cfg.push_assign(else_block, source_info, destination, Rvalue::Use(rhs)); this.cfg.goto(else_block, source_info, join_block); @@ -186,18 +194,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // introduce a unit temporary as the destination for the loop body. let tmp = this.get_unit_temp(); // Execute the body, branching back to the test. - let body_block_end = unpack!(this.expr_into_dest(tmp, body_block, body)); + let body_block_end = + unpack!(this.expr_into_dest(tmp, body_block, &this.thir[body])); this.cfg.goto(body_block_end, source_info, loop_block); // Loops are only exited by `break` expressions. None }) } - ExprKind::Call { ty: _, fun, args, from_hir_call, fn_span } => { - let fun = unpack!(block = this.as_local_operand(block, fun)); + ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => { + let fun = unpack!(block = this.as_local_operand(block, &this.thir[fun])); let args: Vec<_> = args .into_iter() - .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) + .copied() + .map(|arg| unpack!(block = this.as_local_call_operand(block, &this.thir[arg]))) .collect(); let success = this.cfg.start_new_block(); @@ -228,8 +238,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.diverge_from(block); success.unit() } - ExprKind::Use { source } => this.expr_into_dest(destination, block, source), + ExprKind::Use { source } => this.expr_into_dest(destination, block, &this.thir[source]), ExprKind::Borrow { arg, borrow_kind } => { + let arg = &this.thir[arg]; // We don't do this in `as_rvalue` because we use `as_place` // for borrow expressions, so we cannot create an `RValue` that // remains valid across user code. `as_rvalue` is usually called @@ -244,6 +255,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } ExprKind::AddressOf { mutability, arg } => { + let arg = &this.thir[arg]; let place = match mutability { hir::Mutability::Not => this.as_read_only_place(block, arg), hir::Mutability::Mut => this.as_place(block, arg), @@ -252,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, address_of); block.unit() } - ExprKind::Adt { adt_def, variant_index, substs, user_ty, fields, ref base } => { + ExprKind::Adt { adt_def, variant_index, substs, user_ty, ref fields, ref base } => { // See the notes for `ExprKind::Array` in `as_rvalue` and for // `ExprKind::Borrow` above. let is_union = adt_def.is_union(); @@ -264,19 +276,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // (evaluating them in order given by user) let fields_map: FxHashMap<_, _> = fields .into_iter() - .map(|f| (f.name, unpack!(block = this.as_operand(block, Some(scope), f.expr)))) + .map(|f| { + ( + f.name, + unpack!( + block = this.as_operand(block, Some(scope), &this.thir[f.expr]) + ), + ) + }) .collect(); let field_names: Vec<_> = (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect(); let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base { - let place_builder = unpack!(block = this.as_place_builder(block, base)); + let place_builder = + unpack!(block = this.as_place_builder(block, &this.thir[*base])); // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that // reads it from the base. - iter::zip(field_names, *field_types) + iter::zip(field_names, &**field_types) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), None => { @@ -316,7 +336,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); block.unit() } - ExprKind::InlineAsm { template, operands, options, line_spans } => { + ExprKind::InlineAsm { template, ref operands, options, line_spans } => { use crate::thir; use rustc_middle::mir; let operands = operands @@ -324,19 +344,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|op| match *op { thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In { reg, - value: unpack!(block = this.as_local_operand(block, expr)), + value: unpack!(block = this.as_local_operand(block, &this.thir[expr])), }, thir::InlineAsmOperand::Out { reg, late, expr } => { mir::InlineAsmOperand::Out { reg, late, - place: expr - .as_ref() - .map(|expr| unpack!(block = this.as_place(block, expr))), + place: expr.map(|expr| { + unpack!(block = this.as_place(block, &this.thir[expr])) + }), } } thir::InlineAsmOperand::InOut { reg, late, expr } => { - let place = unpack!(block = this.as_place(block, expr)); + let place = unpack!(block = this.as_place(block, &this.thir[expr])); mir::InlineAsmOperand::InOut { reg, late, @@ -349,9 +369,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mir::InlineAsmOperand::InOut { reg, late, - in_value: unpack!(block = this.as_local_operand(block, in_expr)), - out_place: out_expr.as_ref().map(|out_expr| { - unpack!(block = this.as_place(block, out_expr)) + in_value: unpack!( + block = this.as_local_operand(block, &this.thir[in_expr]) + ), + out_place: out_expr.map(|out_expr| { + unpack!(block = this.as_place(block, &this.thir[out_expr])) }), } } @@ -360,9 +382,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { value: box Constant { span, user_ty: None, literal: value.into() }, } } - thir::InlineAsmOperand::SymFn { expr } => { - mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) } - } + thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn { + value: box this.as_constant(&this.thir[expr]), + }, thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } @@ -434,7 +456,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Yield { value } => { let scope = this.local_scope(); - let value = unpack!(block = this.as_operand(block, Some(scope), value)); + let value = unpack!(block = this.as_operand(block, Some(scope), &this.thir[value])); let resume = this.cfg.start_new_block(); this.cfg.terminate( block, diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index f01315fc5db04..d2442f33b0c67 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn stmt_expr( &mut self, mut block: BasicBlock, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, statement_scope: Option, ) -> BlockAnd<()> { let this = self; @@ -24,10 +24,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { this.in_scope((region_scope, source_info), lint_level, |this| { - this.stmt_expr(block, value, statement_scope) + this.stmt_expr(block, &this.thir[value], statement_scope) }) } ExprKind::Assign { lhs, rhs } => { + let lhs = &this.thir[lhs]; + let rhs = &this.thir[rhs]; let lhs_span = lhs.span; // Note: we evaluate assignments right-to-left. This @@ -61,6 +63,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // only affects weird things like `x += {x += 1; x}` // -- is that equal to `x + (x + 1)` or `2*(x+1)`? + let lhs = &this.thir[lhs]; + let rhs = &this.thir[rhs]; let lhs_ty = lhs.ty; debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr); @@ -87,24 +91,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Break { label, value } => this.break_scope( block, - value.as_deref(), + value.map(|value| &this.thir[value]), BreakableTarget::Break(label), source_info, ), - ExprKind::Return { value } => { - this.break_scope(block, value.as_deref(), BreakableTarget::Return, source_info) - } - ExprKind::LlvmInlineAsm { asm, outputs, inputs } => { + ExprKind::Return { value } => this.break_scope( + block, + value.map(|value| &this.thir[value]), + BreakableTarget::Return, + source_info, + ), + ExprKind::LlvmInlineAsm { asm, ref outputs, ref inputs } => { debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr); this.block_context.push(BlockFrame::SubExpr); let outputs = outputs .into_iter() - .map(|output| unpack!(block = this.as_place(block, &output))) + .copied() + .map(|output| unpack!(block = this.as_place(block, &this.thir[output]))) .collect::>() .into_boxed_slice(); let inputs = inputs .into_iter() + .copied() .map(|input| { + let input = &this.thir[input]; (input.span, unpack!(block = this.as_local_operand(block, &input))) }) .collect::>() @@ -139,14 +149,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // than the entirety of block(s) surrounding it. let adjusted_span = (|| { if let ExprKind::Block { body } = &expr.kind { - if let Some(tail_expr) = &body.expr { - let mut expr = &*tail_expr; + if let Some(tail_expr) = body.expr { + let mut expr = &this.thir[tail_expr]; while let ExprKind::Block { body: Block { expr: Some(nested_expr), .. }, } - | ExprKind::Scope { value: nested_expr, .. } = &expr.kind + | ExprKind::Scope { value: nested_expr, .. } = expr.kind { - expr = nested_expr; + expr = &this.thir[nested_expr]; } this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored: true, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 0e422dc3c6378..c30193b5a5a7f 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -90,8 +90,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, span: Span, mut block: BasicBlock, - scrutinee: &Expr<'_, 'tcx>, - arms: &[Arm<'_, 'tcx>], + scrutinee: &Expr<'tcx>, + arms: &[ArmId], ) -> BlockAnd<()> { let scrutinee_span = scrutinee.span; let scrutinee_place = @@ -99,7 +99,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms); - let match_has_guard = arms.iter().any(|arm| arm.guard.is_some()); + let match_has_guard = arms.iter().copied().any(|arm| self.thir[arm].guard.is_some()); let mut candidates = arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::>(); @@ -120,7 +120,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_scrutinee( &mut self, mut block: BasicBlock, - scrutinee: &Expr<'_, 'tcx>, + scrutinee: &Expr<'tcx>, scrutinee_span: Span, ) -> BlockAnd> { let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee)); @@ -156,12 +156,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn create_match_candidates<'pat>( &mut self, scrutinee: PlaceBuilder<'tcx>, - arms: &'pat [Arm<'pat, 'tcx>], - ) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> { + arms: &'pat [ArmId], + ) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)> + where + 'a: 'pat, + { // Assemble a list of candidates: there is one candidate per pattern, // which means there may be more than one candidate *per arm*. arms.iter() + .copied() .map(|arm| { + let arm = &self.thir[arm]; let arm_has_guard = arm.guard.is_some(); let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard); (arm, arm_candidate) @@ -231,7 +236,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, scrutinee_place_builder: PlaceBuilder<'tcx>, scrutinee_span: Span, - arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>, + arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>, outer_source_info: SourceInfo, fake_borrow_temps: Vec<(Place<'tcx>, Local)>, ) -> BlockAnd<()> { @@ -286,7 +291,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.source_scope = source_scope; } - this.expr_into_dest(destination, arm_block, &arm.body) + this.expr_into_dest(destination, arm_block, &&this.thir[arm.body]) }) }) .collect(); @@ -313,7 +318,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, outer_source_info: SourceInfo, candidate: Candidate<'_, 'tcx>, - guard: Option<&Guard<'_, 'tcx>>, + guard: Option<&Guard<'tcx>>, fake_borrow_temps: &Vec<(Place<'tcx>, Local)>, scrutinee_span: Span, arm_span: Option, @@ -389,7 +394,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, irrefutable_pat: Pat<'tcx>, - initializer: &Expr<'_, 'tcx>, + initializer: &Expr<'tcx>, ) -> BlockAnd<()> { match *irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` @@ -1665,7 +1670,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: Candidate<'pat, 'tcx>, parent_bindings: &[(Vec>, Vec>)], - guard: Option<&Guard<'_, 'tcx>>, + guard: Option<&Guard<'tcx>>, fake_borrows: &Vec<(Place<'tcx>, Local)>, scrutinee_span: Span, arm_span: Option, @@ -1799,12 +1804,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow); } - let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match guard { + let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match *guard { Guard::If(e) => { + let e = &self.thir[e]; let source_info = self.source_info(e.span); (e.span, self.test_bool(block, e, source_info)) } - Guard::IfLet(pat, scrutinee) => { + Guard::IfLet(ref pat, scrutinee) => { + let scrutinee = &self.thir[scrutinee]; let scrutinee_span = scrutinee.span; let scrutinee_place_builder = unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span)); @@ -1840,7 +1847,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { guard_candidate, None, &fake_borrow_temps, - scrutinee.span, + scrutinee_span, None, None, ); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index f944e5f8f0420..4f6c57be2daa2 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,7 +1,7 @@ use crate::build; use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; -use crate::thir::{build_thir, Arena, BindingMode, Expr, LintLevel, Pat, PatKind}; +use crate::thir::{build_thir, BindingMode, Expr, ExprId, LintLevel, Pat, PatKind, Thir}; use rustc_attr::{self as attr, UnwindAttr}; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -88,7 +88,6 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // If we don't have a specialized span for the body, just use the // normal def span. let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id)); - let arena = Arena::default(); tcx.infer_ctxt().enter(|infcx| { let body = if let Some(ErrorReported) = typeck_results.tainted_by_errors { @@ -105,7 +104,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ }; let body = tcx.hir().body(body_id); - let thir = build_thir(tcx, def, &arena, &body.value); + let (thir, expr) = build_thir(tcx, def, &body.value); let ty = tcx.type_of(fn_def_id); let mut abi = fn_sig.abi; let implicit_argument = match ty.kind() { @@ -181,6 +180,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ }; let mut mir = build::construct_fn( + &thir, &infcx, def, id, @@ -190,7 +190,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ return_ty, return_ty_span, body, - thir, + expr, span_with_body, ); if yield_ty.is_some() { @@ -213,9 +213,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ let return_ty = typeck_results.node_type(id); let ast_expr = &tcx.hir().body(body_id).value; - let thir = build_thir(tcx, def, &arena, ast_expr); + let (thir, expr) = build_thir(tcx, def, ast_expr); - build::construct_const(&infcx, thir, def, id, return_ty, return_ty_span) + build::construct_const(&thir, &infcx, expr, def, id, return_ty, return_ty_span) }; lints::check(tcx, &body); @@ -323,6 +323,7 @@ struct Builder<'a, 'tcx> { region_scope_tree: &'tcx region::ScopeTree, param_env: ty::ParamEnv<'tcx>, + thir: &'a Thir<'tcx>, cfg: CFG<'tcx>, def_id: DefId, @@ -633,6 +634,7 @@ struct ArgInfo<'tcx>( ); fn construct_fn<'tcx, A>( + thir: &Thir<'tcx>, infcx: &InferCtxt<'_, 'tcx>, fn_def: ty::WithOptConstParam, fn_id: hir::HirId, @@ -642,7 +644,7 @@ fn construct_fn<'tcx, A>( return_ty: Ty<'tcx>, return_ty_span: Span, body: &'tcx hir::Body<'tcx>, - expr: &Expr<'_, 'tcx>, + expr: ExprId, span_with_body: Span, ) -> Body<'tcx> where @@ -654,6 +656,7 @@ where let span = tcx.hir().span(fn_id); let mut builder = Builder::new( + thir, infcx, fn_def, fn_id, @@ -683,7 +686,7 @@ where fn_def.did.to_def_id(), &arguments, arg_scope, - expr, + &thir[expr], ) })) })); @@ -708,8 +711,9 @@ where } fn construct_const<'a, 'tcx>( + thir: &'a Thir<'tcx>, infcx: &'a InferCtxt<'a, 'tcx>, - expr: &Expr<'_, 'tcx>, + expr: ExprId, def: ty::WithOptConstParam, hir_id: hir::HirId, const_ty: Ty<'tcx>, @@ -717,11 +721,21 @@ fn construct_const<'a, 'tcx>( ) -> Body<'tcx> { let tcx = infcx.tcx; let span = tcx.hir().span(hir_id); - let mut builder = - Builder::new(infcx, def, hir_id, span, 0, Safety::Safe, const_ty, const_ty_span, None); + let mut builder = Builder::new( + thir, + infcx, + def, + hir_id, + span, + 0, + Safety::Safe, + const_ty, + const_ty_span, + None, + ); let mut block = START_BLOCK; - unpack!(block = builder.expr_into_dest(Place::return_place(), block, &expr)); + unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr])); let source_info = builder.source_info(span); builder.cfg.terminate(block, source_info, TerminatorKind::Return); @@ -761,22 +775,48 @@ fn construct_error<'a, 'tcx>( hir::BodyOwnerKind::Const => 0, hir::BodyOwnerKind::Static(_) => 0, }; - let mut builder = - Builder::new(infcx, def, hir_id, span, num_params, Safety::Safe, ty, span, generator_kind); - let source_info = builder.source_info(span); + let mut cfg = CFG { basic_blocks: IndexVec::new() }; + let mut source_scopes = IndexVec::new(); + let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1); + + cfg.start_new_block(); + source_scopes.push(SourceScopeData { + span, + parent_scope: None, + inlined: None, + inlined_parent_scope: None, + local_data: ClearCrossCrate::Set(SourceScopeLocalData { + lint_root: hir_id, + safety: Safety::Safe, + }), + }); + let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; + // Some MIR passes will expect the number of parameters to match the // function declaration. for _ in 0..num_params { - builder.local_decls.push(LocalDecl::with_source_info(ty, source_info)); + local_decls.push(LocalDecl::with_source_info(ty, source_info)); } - builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); - let mut body = builder.finish(); + cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); + + let mut body = Body::new( + MirSource::item(def.did.to_def_id()), + cfg.basic_blocks, + source_scopes, + local_decls, + IndexVec::new(), + num_params, + vec![], + span, + generator_kind, + ); body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty)); body } impl<'a, 'tcx> Builder<'a, 'tcx> { fn new( + thir: &'a Thir<'tcx>, infcx: &'a InferCtxt<'a, 'tcx>, def: ty::WithOptConstParam, hir_id: hir::HirId, @@ -803,6 +843,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let lint_level = LintLevel::Explicit(hir_id); let mut builder = Builder { + thir, tcx, infcx, typeck_results: tcx.typeck_opt_const_arg(def), @@ -866,7 +907,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn_def_id: DefId, arguments: &[ArgInfo<'tcx>], argument_scope: region::Scope, - expr: &Expr<'_, 'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd<()> { // Allocate locals for the function arguments for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 41fc925c0494e..e79a19d57ac10 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn break_scope( &mut self, mut block: BasicBlock, - value: Option<&Expr<'_, 'tcx>>, + value: Option<&Expr<'tcx>>, target: BreakableTarget, source_info: SourceInfo, ) -> BlockAnd<()> { @@ -933,7 +933,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn test_bool( &mut self, mut block: BasicBlock, - condition: &Expr<'_, 'tcx>, + condition: &Expr<'tcx>, source_info: SourceInfo, ) -> (BasicBlock, BasicBlock) { let cond = unpack!(block = self.as_local_operand(block, condition)); diff --git a/compiler/rustc_mir_build/src/thir/arena.rs b/compiler/rustc_mir_build/src/thir/arena.rs deleted file mode 100644 index aacc7b12a42f9..0000000000000 --- a/compiler/rustc_mir_build/src/thir/arena.rs +++ /dev/null @@ -1,98 +0,0 @@ -use crate::thir::*; - -macro_rules! declare_arena { - ([], [$($a:tt $name:ident: $ty:ty,)*]) => { - #[derive(Default)] - pub struct Arena<'thir, 'tcx> { - pub dropless: rustc_arena::DroplessArena, - drop: rustc_arena::DropArena, - $($name: rustc_arena::arena_for_type!($a[$ty]),)* - } - - pub trait ArenaAllocatable<'thir, 'tcx, T = Self>: Sized { - fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self; - fn allocate_from_iter( - arena: &'thir Arena<'thir, 'tcx>, - iter: impl ::std::iter::IntoIterator, - ) -> &'thir mut [Self]; - } - - impl<'thir, 'tcx, T: Copy> ArenaAllocatable<'thir, 'tcx, ()> for T { - #[inline] - fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self { - arena.dropless.alloc(self) - } - #[inline] - fn allocate_from_iter( - arena: &'thir Arena<'thir, 'tcx>, - iter: impl ::std::iter::IntoIterator, - ) -> &'thir mut [Self] { - arena.dropless.alloc_from_iter(iter) - } - - } - $( - impl<'thir, 'tcx> ArenaAllocatable<'thir, 'tcx, $ty> for $ty { - #[inline] - fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self { - if !::std::mem::needs_drop::() { - return arena.dropless.alloc(self); - } - match rustc_arena::which_arena_for_type!($a[&arena.$name]) { - ::std::option::Option::<&rustc_arena::TypedArena>::Some(ty_arena) => { - ty_arena.alloc(self) - } - ::std::option::Option::None => unsafe { arena.drop.alloc(self) }, - } - } - - #[inline] - fn allocate_from_iter( - arena: &'thir Arena<'thir, 'tcx>, - iter: impl ::std::iter::IntoIterator, - ) -> &'thir mut [Self] { - if !::std::mem::needs_drop::() { - return arena.dropless.alloc_from_iter(iter); - } - match rustc_arena::which_arena_for_type!($a[&arena.$name]) { - ::std::option::Option::<&rustc_arena::TypedArena>::Some(ty_arena) => { - ty_arena.alloc_from_iter(iter) - } - ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) }, - } - } - } - )* - - impl<'thir, 'tcx> Arena<'thir, 'tcx> { - #[inline] - pub fn alloc, U>(&'thir self, value: T) -> &'thir mut T { - value.allocate_on(self) - } - - #[allow(dead_code)] // function is never used - #[inline] - pub fn alloc_slice(&'thir self, value: &[T]) -> &'thir mut [T] { - if value.is_empty() { - return &mut []; - } - self.dropless.alloc_slice(value) - } - - pub fn alloc_from_iter, U>( - &'thir self, - iter: impl ::std::iter::IntoIterator, - ) -> &'thir mut [T] { - T::allocate_from_iter(self, iter) - } - } - } -} - -declare_arena!([], [ - [] arm: Arm<'thir, 'tcx>, - [] expr: Expr<'thir, 'tcx>, - [] field_expr: FieldExpr<'thir, 'tcx>, - [few] inline_asm_operand: InlineAsmOperand<'thir, 'tcx>, - [] stmt: Stmt<'thir, 'tcx>, -]); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index d450f8a265d99..b90f9abe33a3d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -7,8 +7,8 @@ use rustc_middle::ty; use rustc_index::vec::Idx; -impl<'thir, 'tcx> Cx<'thir, 'tcx> { - crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'thir, 'tcx> { +impl<'tcx> Cx<'tcx> { + crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts); @@ -37,65 +37,78 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { &mut self, block_id: hir::ItemLocalId, stmts: &'tcx [hir::Stmt<'tcx>], - ) -> &'thir [Stmt<'thir, 'tcx>] { - self.arena.alloc_from_iter(stmts.iter().enumerate().filter_map(|(index, stmt)| { - let hir_id = stmt.hir_id; - let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); - match stmt.kind { - hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => Some(Stmt { - kind: StmtKind::Expr { - scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }, - expr: self.mirror_expr(expr), - }, - opt_destruction_scope: opt_dxn_ext, - }), - hir::StmtKind::Item(..) => { - // ignore for purposes of the MIR - None - } - hir::StmtKind::Local(ref local) => { - let remainder_scope = region::Scope { - id: block_id, - data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)), - }; + ) -> Box<[StmtId]> { + stmts + .iter() + .enumerate() + .filter_map(|(index, stmt)| { + let hir_id = stmt.hir_id; + let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); + match stmt.kind { + hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { + let stmt = Stmt { + kind: StmtKind::Expr { + scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node, + }, + expr: self.mirror_expr(expr), + }, + opt_destruction_scope: opt_dxn_ext, + }; + Some(self.thir.stmts.push(stmt)) + } + hir::StmtKind::Item(..) => { + // ignore for purposes of the MIR + None + } + hir::StmtKind::Local(ref local) => { + let remainder_scope = region::Scope { + id: block_id, + data: region::ScopeData::Remainder(region::FirstStatementIndex::new( + index, + )), + }; - let mut pattern = self.pattern_from_hir(local.pat); + let mut pattern = self.pattern_from_hir(local.pat); - if let Some(ty) = &local.ty { - if let Some(&user_ty) = - self.typeck_results.user_provided_types().get(ty.hir_id) - { - debug!("mirror_stmts: user_ty={:?}", user_ty); - pattern = Pat { - ty: pattern.ty, - span: pattern.span, - kind: Box::new(PatKind::AscribeUserType { - ascription: thir::pattern::Ascription { - user_ty: PatTyProj::from_user_type(user_ty), - user_ty_span: ty.span, - variance: ty::Variance::Covariant, - }, - subpattern: pattern, - }), - }; + if let Some(ty) = &local.ty { + if let Some(&user_ty) = + self.typeck_results.user_provided_types().get(ty.hir_id) + { + debug!("mirror_stmts: user_ty={:?}", user_ty); + pattern = Pat { + ty: pattern.ty, + span: pattern.span, + kind: Box::new(PatKind::AscribeUserType { + ascription: thir::pattern::Ascription { + user_ty: PatTyProj::from_user_type(user_ty), + user_ty_span: ty.span, + variance: ty::Variance::Covariant, + }, + subpattern: pattern, + }), + }; + } } - } - Some(Stmt { - kind: StmtKind::Let { - remainder_scope, - init_scope: region::Scope { - id: hir_id.local_id, - data: region::ScopeData::Node, + let stmt = Stmt { + kind: StmtKind::Let { + remainder_scope, + init_scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node, + }, + pattern, + initializer: local.init.map(|init| self.mirror_expr(init)), + lint_level: LintLevel::Explicit(local.hir_id), }, - pattern, - initializer: local.init.map(|init| self.mirror_expr(init)), - lint_level: LintLevel::Explicit(local.hir_id), - }, - opt_destruction_scope: opt_dxn_ext, - }) + opt_destruction_scope: opt_dxn_ext, + }; + Some(self.thir.stmts.push(stmt)) + } } - } - })) + }) + .collect() } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 924278e1a7fb3..9cc7fbdf824d8 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -17,34 +17,17 @@ use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{self, AdtKind, Ty}; use rustc_span::Span; -use std::iter; - -impl<'thir, 'tcx> Cx<'thir, 'tcx> { - /// Mirrors and allocates a single [`hir::Expr`]. If you need to mirror a whole slice - /// of expressions, prefer using [`mirror_exprs`]. - /// - /// [`mirror_exprs`]: Self::mirror_exprs - crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> &'thir Expr<'thir, 'tcx> { +impl<'tcx> Cx<'tcx> { + crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId { // `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow. - ensure_sufficient_stack(|| self.arena.alloc(self.mirror_expr_inner(expr))) + ensure_sufficient_stack(|| self.mirror_expr_inner(expr)) } - /// Mirrors and allocates a slice of [`hir::Expr`]s. They will be allocated as a - /// contiguous sequence in memory. - crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> &'thir [Expr<'thir, 'tcx>] { - self.arena.alloc_from_iter(exprs.iter().map(|expr| self.mirror_expr_inner(expr))) + crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Box<[ExprId]> { + exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect() } - /// Mirrors a [`hir::Expr`] without allocating it into the arena. - /// This is a separate, private function so that [`mirror_expr`] and [`mirror_exprs`] can - /// decide how to allocate this expression (alone or within a slice). - /// - /// [`mirror_expr`]: Self::mirror_expr - /// [`mirror_exprs`]: Self::mirror_exprs - pub(super) fn mirror_expr_inner( - &mut self, - hir_expr: &'tcx hir::Expr<'tcx>, - ) -> Expr<'thir, 'tcx> { + pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId { let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); let expr_scope = region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; @@ -66,7 +49,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { span: hir_expr.span, kind: ExprKind::Scope { region_scope: expr_scope, - value: self.arena.alloc(expr), + value: self.thir.exprs.push(expr), lint_level: LintLevel::Explicit(hir_expr.hir_id), }, }; @@ -81,22 +64,22 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { span: hir_expr.span, kind: ExprKind::Scope { region_scope, - value: self.arena.alloc(expr), + value: self.thir.exprs.push(expr), lint_level: LintLevel::Inherited, }, }; } // OK, all done! - expr + self.thir.exprs.push(expr) } fn apply_adjustment( &mut self, hir_expr: &'tcx hir::Expr<'tcx>, - mut expr: Expr<'thir, 'tcx>, + mut expr: Expr<'tcx>, adjustment: &Adjustment<'tcx>, - ) -> Expr<'thir, 'tcx> { + ) -> Expr<'tcx> { let Expr { temp_lifetime, mut span, .. } = expr; // Adjust the span from the block, to the last expression of the @@ -109,10 +92,10 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { // x // // ^ error message points at this expression. // } - let mut adjust_span = |expr: &mut Expr<'thir, 'tcx>| { + let mut adjust_span = |expr: &mut Expr<'tcx>| { if let ExprKind::Block { body } = &expr.kind { - if let Some(ref last_expr) = body.expr { - span = last_expr.span; + if let Some(last_expr) = body.expr { + span = self.thir[last_expr].span; expr.span = span; } } @@ -121,13 +104,13 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { let kind = match adjustment.kind { Adjust::Pointer(PointerCast::Unsize) => { adjust_span(&mut expr); - ExprKind::Pointer { cast: PointerCast::Unsize, source: self.arena.alloc(expr) } + ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) } } - Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.arena.alloc(expr) }, - Adjust::NeverToAny => ExprKind::NeverToAny { source: self.arena.alloc(expr) }, + Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) }, + Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) }, Adjust::Deref(None) => { adjust_span(&mut expr); - ExprKind::Deref { arg: self.arena.alloc(expr) } + ExprKind::Deref { arg: self.thir.exprs.push(expr) } } Adjust::Deref(Some(deref)) => { // We don't need to do call adjust_span here since @@ -142,30 +125,27 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { span, kind: ExprKind::Borrow { borrow_kind: deref.mutbl.to_borrow_kind(), - arg: self.arena.alloc(expr), + arg: self.thir.exprs.push(expr), }, }; - self.overloaded_place( - hir_expr, - adjustment.target, - Some(call), - self.arena.alloc_from_iter(iter::once(expr)), - deref.span, - ) - } - Adjust::Borrow(AutoBorrow::Ref(_, m)) => { - ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: self.arena.alloc(expr) } + let expr = box [self.thir.exprs.push(expr)]; + + self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span) } + Adjust::Borrow(AutoBorrow::Ref(_, m)) => ExprKind::Borrow { + borrow_kind: m.to_borrow_kind(), + arg: self.thir.exprs.push(expr), + }, Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { - ExprKind::AddressOf { mutability, arg: self.arena.alloc(expr) } + ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(expr) } } }; Expr { temp_lifetime, ty: adjustment.target, span, kind } } - fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'thir, 'tcx> { + fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let expr_ty = self.typeck_results().expr_ty(expr); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); @@ -177,7 +157,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { let args = self.mirror_exprs(args); ExprKind::Call { ty: expr.ty, - fun: self.arena.alloc(expr), + fun: self.thir.exprs.push(expr), args, from_hir_call: true, fn_span, @@ -202,13 +182,12 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { span: expr.span, kind: ExprKind::Tuple { fields: self.mirror_exprs(args) }, }; + let tupled_args = self.thir.exprs.push(tupled_args); ExprKind::Call { ty: method.ty, - fun: self.arena.alloc(method), - args: self - .arena - .alloc_from_iter(vec![self.mirror_expr_inner(fun), tupled_args]), + fun: self.thir.exprs.push(method), + args: box [self.mirror_expr(fun), tupled_args], from_hir_call: true, fn_span: expr.span, } @@ -238,10 +217,14 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { }); debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); - let field_refs = - self.arena.alloc_from_iter(args.iter().enumerate().map(|(idx, e)| { - FieldExpr { name: Field::new(idx), expr: self.mirror_expr(e) } - })); + let field_refs = args + .iter() + .enumerate() + .map(|(idx, e)| FieldExpr { + name: Field::new(idx), + expr: self.mirror_expr(e), + }) + .collect(); ExprKind::Adt { adt_def, substs, @@ -278,9 +261,9 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { if self.typeck_results().is_method_call(expr) { - let lhs = self.mirror_expr_inner(lhs); - let rhs = self.mirror_expr_inner(rhs); - self.overloaded_operator(expr, self.arena.alloc_from_iter(vec![lhs, rhs])) + let lhs = self.mirror_expr(lhs); + let rhs = self.mirror_expr(rhs); + self.overloaded_operator(expr, box [lhs, rhs]) } else { ExprKind::AssignOp { op: bin_op(op.node), @@ -298,9 +281,9 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Binary(op, ref lhs, ref rhs) => { if self.typeck_results().is_method_call(expr) { - let lhs = self.mirror_expr_inner(lhs); - let rhs = self.mirror_expr_inner(rhs); - self.overloaded_operator(expr, self.arena.alloc_from_iter(vec![lhs, rhs])) + let lhs = self.mirror_expr(lhs); + let rhs = self.mirror_expr(rhs); + self.overloaded_operator(expr, box [lhs, rhs]) } else { // FIXME overflow match op.node { @@ -329,15 +312,9 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Index(ref lhs, ref index) => { if self.typeck_results().is_method_call(expr) { - let lhs = self.mirror_expr_inner(lhs); - let index = self.mirror_expr_inner(index); - self.overloaded_place( - expr, - expr_ty, - None, - self.arena.alloc_from_iter(vec![lhs, index]), - expr.span, - ) + let lhs = self.mirror_expr(lhs); + let index = self.mirror_expr(index); + self.overloaded_place(expr, expr_ty, None, box [lhs, index], expr.span) } else { ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) } } @@ -345,14 +322,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { if self.typeck_results().is_method_call(expr) { - let arg = self.mirror_expr_inner(arg); - self.overloaded_place( - expr, - expr_ty, - None, - self.arena.alloc_from_iter(iter::once(arg)), - expr.span, - ) + let arg = self.mirror_expr(arg); + self.overloaded_place(expr, expr_ty, None, box [arg], expr.span) } else { ExprKind::Deref { arg: self.mirror_expr(arg) } } @@ -360,8 +331,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { if self.typeck_results().is_method_call(expr) { - let arg = self.mirror_expr_inner(arg); - self.overloaded_operator(expr, self.arena.alloc_from_iter(iter::once(arg))) + let arg = self.mirror_expr(arg); + self.overloaded_operator(expr, box [arg]) } else { ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) } } @@ -369,8 +340,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { if self.typeck_results().is_method_call(expr) { - let arg = self.mirror_expr_inner(arg); - self.overloaded_operator(expr, self.arena.alloc_from_iter(iter::once(arg))) + let arg = self.mirror_expr(arg); + self.overloaded_operator(expr, box [arg]) } else if let hir::ExprKind::Lit(ref lit) = arg.kind { ExprKind::Literal { literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true), @@ -396,11 +367,10 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { fields: self.field_refs(fields), base: base.as_ref().map(|base| FruInfo { base: self.mirror_expr(base), - field_types: self.arena.alloc_from_iter( - self.typeck_results().fru_field_types()[expr.hir_id] - .iter() - .cloned(), - ), + field_types: self.typeck_results().fru_field_types()[expr.hir_id] + .iter() + .copied() + .collect(), }), } } @@ -447,12 +417,15 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { } }; - let upvars = self.arena.alloc_from_iter( - self.typeck_results - .closure_min_captures_flattened(def_id) - .zip(substs.upvar_tys()) - .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)), - ); + let upvars = self + .typeck_results + .closure_min_captures_flattened(def_id) + .zip(substs.upvar_tys()) + .map(|(captured_place, ty)| { + let upvars = self.capture_upvar(expr, captured_place, ty); + self.thir.exprs.push(upvars) + }) + .collect(); // Convert the closure fake reads, if any, from hir `Place` to ExprRef let fake_reads = match self.typeck_results.closure_fake_reads.get(&def_id) { @@ -460,8 +433,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { .iter() .map(|(place, cause, hir_id)| { let expr = self.convert_captured_hir_place(expr, place.clone()); - let expr_ref: &'thir Expr<'thir, 'tcx> = self.arena.alloc(expr); - (expr_ref, *cause, *hir_id) + (self.thir.exprs.push(expr), *cause, *hir_id) }) .collect(), None => Vec::new(), @@ -477,99 +449,105 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm { template: asm.template, - operands: self.arena.alloc_from_iter(asm.operands.iter().map(|(op, _op_sp)| { - match *op { - hir::InlineAsmOperand::In { reg, ref expr } => { - InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) } - } - hir::InlineAsmOperand::Out { reg, late, ref expr } => { - InlineAsmOperand::Out { + operands: asm + .operands + .iter() + .map(|(op, _op_sp)| { + match *op { + hir::InlineAsmOperand::In { reg, ref expr } => { + InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) } + } + hir::InlineAsmOperand::Out { reg, late, ref expr } => { + InlineAsmOperand::Out { + reg, + late, + expr: expr.as_ref().map(|expr| self.mirror_expr(expr)), + } + } + hir::InlineAsmOperand::InOut { reg, late, ref expr } => { + InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) } + } + hir::InlineAsmOperand::SplitInOut { reg, late, - expr: expr.as_ref().map(|expr| self.mirror_expr(expr)), - } - } - hir::InlineAsmOperand::InOut { reg, late, ref expr } => { - InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) } - } - hir::InlineAsmOperand::SplitInOut { - reg, - late, - ref in_expr, - ref out_expr, - } => InlineAsmOperand::SplitInOut { - reg, - late, - in_expr: self.mirror_expr(in_expr), - out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), - }, - hir::InlineAsmOperand::Const { ref anon_const } => { - let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); - let span = self.tcx.hir().span(anon_const.hir_id); + ref in_expr, + ref out_expr, + } => InlineAsmOperand::SplitInOut { + reg, + late, + in_expr: self.mirror_expr(in_expr), + out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), + }, + hir::InlineAsmOperand::Const { ref anon_const } => { + let anon_const_def_id = + self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let span = self.tcx.hir().span(anon_const.hir_id); - InlineAsmOperand::Const { value, span } - } - hir::InlineAsmOperand::Sym { ref expr } => { - let qpath = match expr.kind { - hir::ExprKind::Path(ref qpath) => qpath, - _ => span_bug!( - expr.span, - "asm `sym` operand should be a path, found {:?}", - expr.kind - ), - }; - let temp_lifetime = - self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let res = self.typeck_results().qpath_res(qpath, expr.hir_id); - let ty; - match res { - Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => { - ty = self.typeck_results().node_type(expr.hir_id); - let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); - InlineAsmOperand::SymFn { - expr: self.arena.alloc(Expr { - ty, - temp_lifetime, - span: expr.span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(self.tcx, ty), - user_ty, - const_id: None, - }, - }), + InlineAsmOperand::Const { value, span } + } + hir::InlineAsmOperand::Sym { ref expr } => { + let qpath = match expr.kind { + hir::ExprKind::Path(ref qpath) => qpath, + _ => span_bug!( + expr.span, + "asm `sym` operand should be a path, found {:?}", + expr.kind + ), + }; + let temp_lifetime = + self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let res = self.typeck_results().qpath_res(qpath, expr.hir_id); + let ty; + match res { + Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => { + ty = self.typeck_results().node_type(expr.hir_id); + let user_ty = + self.user_substs_applied_to_res(expr.hir_id, res); + InlineAsmOperand::SymFn { + expr: self.thir.exprs.push(Expr { + ty, + temp_lifetime, + span: expr.span, + kind: ExprKind::Literal { + literal: ty::Const::zero_sized(self.tcx, ty), + user_ty, + const_id: None, + }, + }), + } } - } - Res::Def(DefKind::Static, def_id) => { - InlineAsmOperand::SymStatic { def_id } - } + Res::Def(DefKind::Static, def_id) => { + InlineAsmOperand::SymStatic { def_id } + } - _ => { - self.tcx.sess.span_err( - expr.span, - "asm `sym` operand must point to a fn or static", - ); - - // Not a real fn, but we're not reaching codegen anyways... - ty = self.tcx.ty_error(); - InlineAsmOperand::SymFn { - expr: self.arena.alloc(Expr { - ty, - temp_lifetime, - span: expr.span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(self.tcx, ty), - user_ty: None, - const_id: None, - }, - }), + _ => { + self.tcx.sess.span_err( + expr.span, + "asm `sym` operand must point to a fn or static", + ); + + // Not a real fn, but we're not reaching codegen anyways... + ty = self.tcx.ty_error(); + InlineAsmOperand::SymFn { + expr: self.thir.exprs.push(Expr { + ty, + temp_lifetime, + span: expr.span, + kind: ExprKind::Literal { + literal: ty::Const::zero_sized(self.tcx, ty), + user_ty: None, + const_id: None, + }, + }), + } } } } } - } - })), + }) + .collect(), options: asm.options, line_spans: asm.line_spans, }, @@ -616,13 +594,13 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { }, hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { scrutinee: self.mirror_expr(discr), - arms: self.arena.alloc_from_iter(arms.iter().map(|a| self.convert_arm(a))), + arms: arms.iter().map(|a| self.convert_arm(a)).collect(), }, hir::ExprKind::Loop(ref body, ..) => { let block_ty = self.typeck_results().node_type(body.hir_id); let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id); let block = self.mirror_block(body); - let body = self.arena.alloc(Expr { + let body = self.thir.exprs.push(Expr { ty: block_ty, temp_lifetime, span: block.span, @@ -692,35 +670,34 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { }; let source = if let Some((did, offset, var_ty)) = var { - let mk_const = |literal| { - self.arena.alloc(Expr { - temp_lifetime, - ty: var_ty, - span: expr.span, - kind: ExprKind::Literal { literal, user_ty: None, const_id: None }, - }) + let mk_const = |literal| Expr { + temp_lifetime, + ty: var_ty, + span: expr.span, + kind: ExprKind::Literal { literal, user_ty: None, const_id: None }, }; - let offset = mk_const(ty::Const::from_bits( + let offset = self.thir.exprs.push(mk_const(ty::Const::from_bits( self.tcx, offset as u128, self.param_env.and(var_ty), - )); + ))); match did { Some(did) => { // in case we are offsetting from a computed discriminant // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(self.tcx(), did); - let lhs = mk_const(self.tcx().mk_const(ty::Const { + let lhs = ty::Const { val: ty::ConstKind::Unevaluated(ty::Unevaluated { def: ty::WithOptConstParam::unknown(did), substs, promoted: None, }), ty: var_ty, - })); + }; + let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs))); let bin = ExprKind::Binary { op: BinOp::Add, lhs: lhs, rhs: offset }; - self.arena.alloc(Expr { + self.thir.exprs.push(Expr { temp_lifetime, ty: var_ty, span: expr.span, @@ -739,7 +716,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { if let Some(user_ty) = user_ty { // NOTE: Creating a new Expr and wrapping a Cast inside of it may be // inefficient, revisit this when performance becomes an issue. - let cast_expr = self.arena.alloc(Expr { + let cast_expr = self.thir.exprs.push(Expr { temp_lifetime, ty: expr_ty, span: expr.span, @@ -819,7 +796,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { expr: &hir::Expr<'_>, span: Span, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, - ) -> Expr<'thir, 'tcx> { + ) -> Expr<'tcx> { let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let (def_id, substs, user_ty) = match overloaded_callee { Some((def_id, substs)) => (def_id, substs, None), @@ -846,8 +823,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { } } - fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'thir, 'tcx> { - Arm { + fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId { + let arm = Arm { pattern: self.pattern_from_hir(&arm.pat), guard: arm.guard.as_ref().map(|g| match g { hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)), @@ -859,14 +836,11 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { lint_level: LintLevel::Explicit(arm.hir_id), scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }, span: arm.span, - } + }; + self.thir.arms.push(arm) } - fn convert_path_expr( - &mut self, - expr: &'tcx hir::Expr<'tcx>, - res: Res, - ) -> ExprKind<'thir, 'tcx> { + fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { let substs = self.typeck_results().node_substs(expr.hir_id); match res { // A regular function, constructor function or a constant. @@ -934,7 +908,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { variant_index: adt_def.variant_index_with_ctor_id(def_id), substs, user_ty: user_provided_type, - fields: self.arena.alloc_from_iter(iter::empty()), + fields: box [], base: None, }, _ => bug!("unexpected ty: {:?}", ty), @@ -956,7 +930,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { } }; ExprKind::Deref { - arg: self.arena.alloc(Expr { ty, temp_lifetime, span: expr.span, kind }), + arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }), } } @@ -966,7 +940,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { } } - fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'thir, 'tcx> { + fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> { // We want upvars here not captures. // Captures will be handled in MIR. let is_upvar = self @@ -989,10 +963,17 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { fn overloaded_operator( &mut self, expr: &'tcx hir::Expr<'tcx>, - args: &'thir [Expr<'thir, 'tcx>], - ) -> ExprKind<'thir, 'tcx> { - let fun = self.arena.alloc(self.method_callee(expr, expr.span, None)); - ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span } + args: Box<[ExprId]>, + ) -> ExprKind<'tcx> { + let fun = self.method_callee(expr, expr.span, None); + let fun = self.thir.exprs.push(fun); + ExprKind::Call { + ty: self.thir[fun].ty, + fun, + args, + from_hir_call: false, + fn_span: expr.span, + } } fn overloaded_place( @@ -1000,9 +981,9 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { expr: &'tcx hir::Expr<'tcx>, place_ty: Ty<'tcx>, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, - args: &'thir [Expr<'thir, 'tcx>], + args: Box<[ExprId]>, span: Span, - ) -> ExprKind<'thir, 'tcx> { + ) -> ExprKind<'tcx> { // For an overloaded *x or x[y] expression of type T, the method // call returns an &T and we must add the deref so that the types // line up (this is because `*x` and `x[y]` represent places): @@ -1010,7 +991,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. - let (region, mutbl) = match *args[0].ty.kind() { + let (region, mutbl) = match *self.thir[args[0]].ty.kind() { ty::Ref(region, _, mutbl) => (region, mutbl), _ => span_bug!(span, "overloaded_place: receiver is not a reference"), }; @@ -1019,12 +1000,14 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let fun = self.arena.alloc(self.method_callee(expr, span, overloaded_callee)); - let ref_expr = self.arena.alloc(Expr { + let fun = self.method_callee(expr, span, overloaded_callee); + let fun = self.thir.exprs.push(fun); + let fun_ty = self.thir[fun].ty; + let ref_expr = self.thir.exprs.push(Expr { temp_lifetime, ty: ref_ty, span, - kind: ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: span }, + kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span }, }); // construct and return a deref wrapper `*foo()` @@ -1035,7 +1018,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { &mut self, closure_expr: &'tcx hir::Expr<'tcx>, place: HirPlace<'tcx>, - ) -> Expr<'thir, 'tcx> { + ) -> Expr<'tcx> { let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); let var_ty = place.base_ty; @@ -1059,13 +1042,13 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { for proj in place.projections.iter() { let kind = match proj.kind { HirProjectionKind::Deref => { - ExprKind::Deref { arg: self.arena.alloc(captured_place_expr) } + ExprKind::Deref { arg: self.thir.exprs.push(captured_place_expr) } } HirProjectionKind::Field(field, ..) => { // Variant index will always be 0, because for multi-variant // enums, we capture the enum entirely. ExprKind::Field { - lhs: self.arena.alloc(captured_place_expr), + lhs: self.thir.exprs.push(captured_place_expr), name: Field::new(field as usize), } } @@ -1087,7 +1070,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { closure_expr: &'tcx hir::Expr<'tcx>, captured_place: &'tcx ty::CapturedPlace<'tcx>, upvar_ty: Ty<'tcx>, - ) -> Expr<'thir, 'tcx> { + ) -> Expr<'tcx> { let upvar_capture = captured_place.info.capture_kind; let captured_place_expr = self.convert_captured_hir_place(closure_expr, captured_place.place.clone()); @@ -1107,7 +1090,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { span: closure_expr.span, kind: ExprKind::Borrow { borrow_kind, - arg: self.arena.alloc(captured_place_expr), + arg: self.thir.exprs.push(captured_place_expr), }, } } @@ -1115,14 +1098,14 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { } /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr. - fn field_refs( - &mut self, - fields: &'tcx [hir::ExprField<'tcx>], - ) -> &'thir [FieldExpr<'thir, 'tcx>] { - self.arena.alloc_from_iter(fields.iter().map(|field| FieldExpr { - name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), - expr: self.mirror_expr(field.expr), - })) + fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> { + fields + .iter() + .map(|field| FieldExpr { + name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), + expr: self.mirror_expr(field.expr), + }) + .collect() } } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index c0433604f8c68..aad6319e40434 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -2,7 +2,6 @@ //! structures into the THIR. The `builder` is generally ignorant of the tcx, //! etc., and instead goes through the `Cx` for most of its work. -use crate::thir::arena::Arena; use crate::thir::util::UserAnnotatedTyHelpers; use crate::thir::*; @@ -14,18 +13,19 @@ use rustc_middle::middle::region; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::{self, Ty, TyCtxt}; -pub fn build_thir<'thir, 'tcx>( +pub fn build_thir<'tcx>( tcx: TyCtxt<'tcx>, owner_def: ty::WithOptConstParam, - arena: &'thir Arena<'thir, 'tcx>, expr: &'tcx hir::Expr<'tcx>, -) -> &'thir Expr<'thir, 'tcx> { - Cx::new(tcx, owner_def, &arena).mirror_expr(expr) +) -> (Thir<'tcx>, ExprId) { + let mut cx = Cx::new(tcx, owner_def); + let expr = cx.mirror_expr(expr); + (cx.thir, expr) } -struct Cx<'thir, 'tcx> { +struct Cx<'tcx> { tcx: TyCtxt<'tcx>, - arena: &'thir Arena<'thir, 'tcx>, + thir: Thir<'tcx>, crate param_env: ty::ParamEnv<'tcx>, @@ -36,16 +36,12 @@ struct Cx<'thir, 'tcx> { body_owner: DefId, } -impl<'thir, 'tcx> Cx<'thir, 'tcx> { - fn new( - tcx: TyCtxt<'tcx>, - def: ty::WithOptConstParam, - arena: &'thir Arena<'thir, 'tcx>, - ) -> Cx<'thir, 'tcx> { +impl<'tcx> Cx<'tcx> { + fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam) -> Cx<'tcx> { let typeck_results = tcx.typeck_opt_const_arg(def); Cx { tcx, - arena, + thir: Thir::new(), param_env: tcx.param_env(def.did), region_scope_tree: tcx.region_scope_tree(def.did), typeck_results, @@ -87,7 +83,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { } } -impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> { +impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index 9bcb000920c04..d188d17dd56a5 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -7,6 +7,8 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_index::newtype_index; +use rustc_index::vec::IndexVec; use rustc_middle::infer::canonical::Canonical; use rustc_middle::middle::region; use rustc_middle::mir::{BinOp, BorrowKind, FakeReadCause, Field, UnOp}; @@ -17,6 +19,8 @@ use rustc_span::Span; use rustc_target::abi::VariantIdx; use rustc_target::asm::InlineAsmRegOrRegClass; +use std::ops::Index; + crate mod constant; crate mod cx; @@ -25,12 +29,62 @@ pub use cx::build_thir; crate mod pattern; pub use self::pattern::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj}; -mod arena; -pub use arena::Arena; - mod util; pub mod visit; +newtype_index! { + pub struct ArmId { + DEBUG_FORMAT = "a{}" + } +} + +newtype_index! { + pub struct ExprId { + DEBUG_FORMAT = "e{}" + } +} + +newtype_index! { + pub struct StmtId { + DEBUG_FORMAT = "s{}" + } +} + +macro_rules! thir_with_elements { + ($($name:ident: $id:ty => $value:ty,)*) => { + pub struct Thir<'tcx> { + $( + $name: IndexVec<$id, $value>, + )* + } + + impl<'tcx> Thir<'tcx> { + fn new() -> Thir<'tcx> { + Thir { + $( + $name: IndexVec::new(), + )* + } + } + } + + $( + impl<'tcx> Index<$id> for Thir<'tcx> { + type Output = $value; + fn index(&self, index: $id) -> &Self::Output { + &self.$name[index] + } + } + )* + } +} + +thir_with_elements! { + arms: ArmId => Arm<'tcx>, + exprs: ExprId => Expr<'tcx>, + stmts: StmtId => Stmt<'tcx>, +} + #[derive(Copy, Clone, Debug)] pub enum LintLevel { Inherited, @@ -38,13 +92,13 @@ pub enum LintLevel { } #[derive(Debug)] -pub struct Block<'thir, 'tcx> { +pub struct Block { pub targeted_by_break: bool, pub region_scope: region::Scope, pub opt_destruction_scope: Option, pub span: Span, - pub stmts: &'thir [Stmt<'thir, 'tcx>], - pub expr: Option<&'thir Expr<'thir, 'tcx>>, + pub stmts: Box<[StmtId]>, + pub expr: Option, pub safety_mode: BlockSafety, } @@ -57,19 +111,19 @@ pub enum BlockSafety { } #[derive(Debug)] -pub struct Stmt<'thir, 'tcx> { - pub kind: StmtKind<'thir, 'tcx>, +pub struct Stmt<'tcx> { + pub kind: StmtKind<'tcx>, pub opt_destruction_scope: Option, } #[derive(Debug)] -pub enum StmtKind<'thir, 'tcx> { +pub enum StmtKind<'tcx> { Expr { /// scope for this statement; may be used as lifetime of temporaries scope: region::Scope, /// expression being evaluated in this statement - expr: &'thir Expr<'thir, 'tcx>, + expr: ExprId, }, Let { @@ -87,7 +141,7 @@ pub enum StmtKind<'thir, 'tcx> { pattern: Pat<'tcx>, /// let pat: ty = ... - initializer: Option<&'thir Expr<'thir, 'tcx>>, + initializer: Option, /// the lint level for this let-statement lint_level: LintLevel, @@ -96,12 +150,12 @@ pub enum StmtKind<'thir, 'tcx> { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144); +rustc_data_structures::static_assert_size!(Expr<'_>, 144); /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) /// into instances of this `Expr` enum. This lowering can be done /// basically as lazily or as eagerly as desired: every recursive -/// reference to an expression in this enum is an `&'thir Expr<'thir, 'tcx>`, which +/// reference to an expression in this enum is an `ExprId`, which /// may in turn be another instance of this enum (boxed), or else an /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very /// short-lived. They are created by `Thir::to_expr`, analyzed and @@ -113,7 +167,7 @@ rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144); /// example, method calls and overloaded operators are absent: they are /// expected to be converted into `Expr::Call` instances. #[derive(Debug)] -pub struct Expr<'thir, 'tcx> { +pub struct Expr<'tcx> { /// type of this expression pub ty: Ty<'tcx>, @@ -125,28 +179,28 @@ pub struct Expr<'thir, 'tcx> { pub span: Span, /// kind of expression - pub kind: ExprKind<'thir, 'tcx>, + pub kind: ExprKind<'tcx>, } #[derive(Debug)] -pub enum ExprKind<'thir, 'tcx> { +pub enum ExprKind<'tcx> { Scope { region_scope: region::Scope, lint_level: LintLevel, - value: &'thir Expr<'thir, 'tcx>, + value: ExprId, }, Box { - value: &'thir Expr<'thir, 'tcx>, + value: ExprId, }, If { - cond: &'thir Expr<'thir, 'tcx>, - then: &'thir Expr<'thir, 'tcx>, - else_opt: Option<&'thir Expr<'thir, 'tcx>>, + cond: ExprId, + then: ExprId, + else_opt: Option, }, Call { ty: Ty<'tcx>, - fun: &'thir Expr<'thir, 'tcx>, - args: &'thir [Expr<'thir, 'tcx>], + fun: ExprId, + args: Box<[ExprId]>, /// Whether this is from a call in HIR, rather than from an overloaded /// operator. `true` for overloaded function call. from_hir_call: bool, @@ -155,62 +209,62 @@ pub enum ExprKind<'thir, 'tcx> { fn_span: Span, }, Deref { - arg: &'thir Expr<'thir, 'tcx>, + arg: ExprId, }, // NOT overloaded! Binary { op: BinOp, - lhs: &'thir Expr<'thir, 'tcx>, - rhs: &'thir Expr<'thir, 'tcx>, + lhs: ExprId, + rhs: ExprId, }, // NOT overloaded! LogicalOp { op: LogicalOp, - lhs: &'thir Expr<'thir, 'tcx>, - rhs: &'thir Expr<'thir, 'tcx>, + lhs: ExprId, + rhs: ExprId, }, // NOT overloaded! // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands. Unary { op: UnOp, - arg: &'thir Expr<'thir, 'tcx>, + arg: ExprId, }, // NOT overloaded! Cast { - source: &'thir Expr<'thir, 'tcx>, + source: ExprId, }, Use { - source: &'thir Expr<'thir, 'tcx>, + source: ExprId, }, // Use a lexpr to get a vexpr. NeverToAny { - source: &'thir Expr<'thir, 'tcx>, + source: ExprId, }, Pointer { cast: PointerCast, - source: &'thir Expr<'thir, 'tcx>, + source: ExprId, }, Loop { - body: &'thir Expr<'thir, 'tcx>, + body: ExprId, }, Match { - scrutinee: &'thir Expr<'thir, 'tcx>, - arms: &'thir [Arm<'thir, 'tcx>], + scrutinee: ExprId, + arms: Box<[ArmId]>, }, Block { - body: Block<'thir, 'tcx>, + body: Block, }, Assign { - lhs: &'thir Expr<'thir, 'tcx>, - rhs: &'thir Expr<'thir, 'tcx>, + lhs: ExprId, + rhs: ExprId, }, AssignOp { op: BinOp, - lhs: &'thir Expr<'thir, 'tcx>, - rhs: &'thir Expr<'thir, 'tcx>, + lhs: ExprId, + rhs: ExprId, }, Field { - lhs: &'thir Expr<'thir, 'tcx>, + lhs: ExprId, name: Field, }, Index { - lhs: &'thir Expr<'thir, 'tcx>, - index: &'thir Expr<'thir, 'tcx>, + lhs: ExprId, + index: ExprId, }, VarRef { id: hir::HirId, @@ -225,35 +279,35 @@ pub enum ExprKind<'thir, 'tcx> { }, Borrow { borrow_kind: BorrowKind, - arg: &'thir Expr<'thir, 'tcx>, + arg: ExprId, }, /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. AddressOf { mutability: hir::Mutability, - arg: &'thir Expr<'thir, 'tcx>, + arg: ExprId, }, Break { label: region::Scope, - value: Option<&'thir Expr<'thir, 'tcx>>, + value: Option, }, Continue { label: region::Scope, }, Return { - value: Option<&'thir Expr<'thir, 'tcx>>, + value: Option, }, ConstBlock { value: &'tcx Const<'tcx>, }, Repeat { - value: &'thir Expr<'thir, 'tcx>, + value: ExprId, count: &'tcx Const<'tcx>, }, Array { - fields: &'thir [Expr<'thir, 'tcx>], + fields: Box<[ExprId]>, }, Tuple { - fields: &'thir [Expr<'thir, 'tcx>], + fields: Box<[ExprId]>, }, Adt { adt_def: &'tcx AdtDef, @@ -264,25 +318,25 @@ pub enum ExprKind<'thir, 'tcx> { /// Bar:: { ... }`. user_ty: Option>>, - fields: &'thir [FieldExpr<'thir, 'tcx>], - base: Option>, + fields: Box<[FieldExpr]>, + base: Option>, }, PlaceTypeAscription { - source: &'thir Expr<'thir, 'tcx>, + source: ExprId, /// Type that the user gave to this expression user_ty: Option>>, }, ValueTypeAscription { - source: &'thir Expr<'thir, 'tcx>, + source: ExprId, /// Type that the user gave to this expression user_ty: Option>>, }, Closure { closure_id: DefId, substs: UpvarSubsts<'tcx>, - upvars: &'thir [Expr<'thir, 'tcx>], + upvars: Box<[ExprId]>, movability: Option, - fake_reads: Vec<(&'thir Expr<'thir, 'tcx>, FakeReadCause, hir::HirId)>, + fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>, }, Literal { literal: &'tcx Const<'tcx>, @@ -302,7 +356,7 @@ pub enum ExprKind<'thir, 'tcx> { }, InlineAsm { template: &'tcx [InlineAsmTemplatePiece], - operands: &'thir [InlineAsmOperand<'thir, 'tcx>], + operands: Box<[InlineAsmOperand<'tcx>]>, options: InlineAsmOptions, line_spans: &'tcx [Span], }, @@ -310,40 +364,40 @@ pub enum ExprKind<'thir, 'tcx> { ThreadLocalRef(DefId), LlvmInlineAsm { asm: &'tcx hir::LlvmInlineAsmInner, - outputs: &'thir [Expr<'thir, 'tcx>], - inputs: &'thir [Expr<'thir, 'tcx>], + outputs: Box<[ExprId]>, + inputs: Box<[ExprId]>, }, Yield { - value: &'thir Expr<'thir, 'tcx>, + value: ExprId, }, } #[derive(Debug)] -pub struct FieldExpr<'thir, 'tcx> { +pub struct FieldExpr { pub name: Field, - pub expr: &'thir Expr<'thir, 'tcx>, + pub expr: ExprId, } #[derive(Debug)] -pub struct FruInfo<'thir, 'tcx> { - pub base: &'thir Expr<'thir, 'tcx>, - pub field_types: &'thir [Ty<'tcx>], +pub struct FruInfo<'tcx> { + pub base: ExprId, + pub field_types: Box<[Ty<'tcx>]>, } #[derive(Debug)] -pub struct Arm<'thir, 'tcx> { +pub struct Arm<'tcx> { pub pattern: Pat<'tcx>, - pub guard: Option>, - pub body: &'thir Expr<'thir, 'tcx>, + pub guard: Option>, + pub body: ExprId, pub lint_level: LintLevel, pub scope: region::Scope, pub span: Span, } #[derive(Debug)] -pub enum Guard<'thir, 'tcx> { - If(&'thir Expr<'thir, 'tcx>), - IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>), +pub enum Guard<'tcx> { + If(ExprId), + IfLet(Pat<'tcx>, ExprId), } #[derive(Copy, Clone, Debug)] @@ -353,33 +407,33 @@ pub enum LogicalOp { } #[derive(Debug)] -pub enum InlineAsmOperand<'thir, 'tcx> { +pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, - expr: &'thir Expr<'thir, 'tcx>, + expr: ExprId, }, Out { reg: InlineAsmRegOrRegClass, late: bool, - expr: Option<&'thir Expr<'thir, 'tcx>>, + expr: Option, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, - expr: &'thir Expr<'thir, 'tcx>, + expr: ExprId, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, - in_expr: &'thir Expr<'thir, 'tcx>, - out_expr: Option<&'thir Expr<'thir, 'tcx>>, + in_expr: ExprId, + out_expr: Option, }, Const { value: &'tcx Const<'tcx>, span: Span, }, SymFn { - expr: &'thir Expr<'thir, 'tcx>, + expr: ExprId, }, SymStatic { def_id: DefId, From 7093a21e27e1711460eb912c6acb15f4501de81e Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 13 May 2021 22:01:25 +0200 Subject: [PATCH 2/2] Adapt the THIR visitor to the vec-stored THIR --- .../rustc_mir_build/src/check_unsafety.rs | 37 +++-- compiler/rustc_mir_build/src/thir/visit.rs | 154 +++++++++--------- 2 files changed, 96 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 83288fa541e44..3ef1155b91688 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -9,8 +9,9 @@ use rustc_session::lint::Level; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; -struct UnsafetyVisitor<'tcx> { +struct UnsafetyVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, + thir: &'a Thir<'tcx>, /// The `HirId` of the current scope, which would be the `HirId` /// of the current HIR node, modulo adjustments. Used for lint levels. hir_context: hir::HirId, @@ -20,7 +21,7 @@ struct UnsafetyVisitor<'tcx> { body_unsafety: BodyUnsafety, } -impl<'tcx> UnsafetyVisitor<'tcx> { +impl<'tcx> UnsafetyVisitor<'_, 'tcx> { fn in_safety_context( &mut self, safety_context: SafetyContext, @@ -127,8 +128,12 @@ impl<'tcx> UnsafetyVisitor<'tcx> { } } -impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> { - fn visit_block(&mut self, block: &Block<'thir, 'tcx>) { +impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { + fn thir(&self) -> &'a Thir<'tcx> { + &self.thir + } + + fn visit_block(&mut self, block: &Block) { if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode { self.in_safety_context( SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false }, @@ -139,17 +144,17 @@ impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> { } } - fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) { + fn visit_expr(&mut self, expr: &Expr<'tcx>) { match expr.kind { ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => { let prev_id = self.hir_context; self.hir_context = hir_id; - self.visit_expr(value); + self.visit_expr(&self.thir[value]); self.hir_context = prev_id; return; } ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => { - if fun.ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { self.requires_unsafe(expr.span, CallToUnsafeFunction); } } @@ -293,7 +298,12 @@ impl UnsafeOpKind { // FIXME: checking unsafety for closures should be handled by their parent body, // as they inherit their "safety context" from their declaration site. -pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, thir: &Expr<'_, 'tcx>, hir_id: hir::HirId) { +pub fn check_unsafety<'tcx>( + tcx: TyCtxt<'tcx>, + thir: &Thir<'tcx>, + expr: ExprId, + hir_id: hir::HirId, +) { let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| { if fn_sig.header.unsafety == hir::Unsafety::Unsafe { BodyUnsafety::Unsafe(fn_sig.span) @@ -303,8 +313,9 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, thir: &Expr<'_, 'tcx>, hir_id: hi }); let safety_context = if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe }; - let mut visitor = UnsafetyVisitor { tcx, safety_context, hir_context: hir_id, body_unsafety }; - visitor.visit_expr(thir); + let mut visitor = + UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety }; + visitor.visit_expr(&thir[expr]); } crate fn thir_check_unsafety_inner<'tcx>( @@ -314,10 +325,8 @@ crate fn thir_check_unsafety_inner<'tcx>( let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let body_id = tcx.hir().body_owned_by(hir_id); let body = tcx.hir().body(body_id); - - let arena = Arena::default(); - let thir = cx::build_thir(tcx, def, &arena, &body.value); - check_unsafety(tcx, thir, hir_id); + let (thir, expr) = cx::build_thir(tcx, def, &body.value); + check_unsafety(tcx, &thir, expr, hir_id); } crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_mir_build/src/thir/visit.rs index 9c5b07e2b2ada..671d1fe9b0305 100644 --- a/compiler/rustc_mir_build/src/thir/visit.rs +++ b/compiler/rustc_mir_build/src/thir/visit.rs @@ -1,123 +1,124 @@ use crate::thir::*; -pub trait Visitor<'thir, 'tcx>: Sized { - fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) { +pub trait Visitor<'a, 'tcx: 'a>: Sized { + fn thir(&self) -> &'a Thir<'tcx>; + + fn visit_expr(&mut self, expr: &Expr<'tcx>) { walk_expr(self, expr); } - fn visit_stmt(&mut self, stmt: &'thir Stmt<'thir, 'tcx>) { + fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { walk_stmt(self, stmt); } - fn visit_block(&mut self, block: &Block<'thir, 'tcx>) { + fn visit_block(&mut self, block: &Block) { walk_block(self, block); } - fn visit_arm(&mut self, arm: &'thir Arm<'thir, 'tcx>) { + fn visit_arm(&mut self, arm: &Arm<'tcx>) { walk_arm(self, arm); } fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} } -pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>( - visitor: &mut V, - expr: &'thir Expr<'thir, 'tcx>, -) { +pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { use ExprKind::*; match expr.kind { - Scope { value, region_scope: _, lint_level: _ } => visitor.visit_expr(value), - Box { value } => visitor.visit_expr(value), + Scope { value, region_scope: _, lint_level: _ } => { + visitor.visit_expr(&visitor.thir()[value]) + } + Box { value } => visitor.visit_expr(&visitor.thir()[value]), If { cond, then, else_opt } => { - visitor.visit_expr(cond); - visitor.visit_expr(then); + visitor.visit_expr(&visitor.thir()[cond]); + visitor.visit_expr(&visitor.thir()[then]); if let Some(else_expr) = else_opt { - visitor.visit_expr(else_expr); + visitor.visit_expr(&visitor.thir()[else_expr]); } } - Call { fun, args, ty: _, from_hir_call: _, fn_span: _ } => { - visitor.visit_expr(fun); - for arg in args { - visitor.visit_expr(arg); + Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => { + visitor.visit_expr(&visitor.thir()[fun]); + for &arg in &**args { + visitor.visit_expr(&visitor.thir()[arg]); } } - Deref { arg } => visitor.visit_expr(arg), + Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { - visitor.visit_expr(lhs); - visitor.visit_expr(rhs); - } - Unary { arg, op: _ } => visitor.visit_expr(arg), - Cast { source } => visitor.visit_expr(source), - Use { source } => visitor.visit_expr(source), - NeverToAny { source } => visitor.visit_expr(source), - Pointer { source, cast: _ } => visitor.visit_expr(source), - Loop { body } => visitor.visit_expr(body), - Match { scrutinee, arms } => { - visitor.visit_expr(scrutinee); - for arm in arms { - visitor.visit_arm(arm); + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[rhs]); + } + Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]), + Cast { source } => visitor.visit_expr(&visitor.thir()[source]), + Use { source } => visitor.visit_expr(&visitor.thir()[source]), + NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), + Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), + Loop { body } => visitor.visit_expr(&visitor.thir()[body]), + Match { scrutinee, ref arms } => { + visitor.visit_expr(&visitor.thir()[scrutinee]); + for &arm in &**arms { + visitor.visit_arm(&visitor.thir()[arm]); } } Block { ref body } => visitor.visit_block(body), Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { - visitor.visit_expr(lhs); - visitor.visit_expr(rhs); + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[rhs]); } - Field { lhs, name: _ } => visitor.visit_expr(lhs), + Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]), Index { lhs, index } => { - visitor.visit_expr(lhs); - visitor.visit_expr(index); + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[index]); } VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} - Borrow { arg, borrow_kind: _ } => visitor.visit_expr(arg), - AddressOf { arg, mutability: _ } => visitor.visit_expr(arg), + Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), + AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), Break { value, label: _ } => { if let Some(value) = value { - visitor.visit_expr(value) + visitor.visit_expr(&visitor.thir()[value]) } } Continue { label: _ } => {} Return { value } => { if let Some(value) = value { - visitor.visit_expr(value) + visitor.visit_expr(&visitor.thir()[value]) } } ConstBlock { value } => visitor.visit_const(value), Repeat { value, count } => { - visitor.visit_expr(value); + visitor.visit_expr(&visitor.thir()[value]); visitor.visit_const(count); } - Array { fields } | Tuple { fields } => { - for field in fields { - visitor.visit_expr(field); + Array { ref fields } | Tuple { ref fields } => { + for &field in &**fields { + visitor.visit_expr(&visitor.thir()[field]); } } - Adt { fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => { - for field in fields { - visitor.visit_expr(field.expr); + Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => { + for field in &**fields { + visitor.visit_expr(&visitor.thir()[field.expr]); } if let Some(base) = base { - visitor.visit_expr(base.base); + visitor.visit_expr(&visitor.thir()[base.base]); } } PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => { - visitor.visit_expr(source) + visitor.visit_expr(&visitor.thir()[source]) } Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), StaticRef { literal, def_id: _ } => visitor.visit_const(literal), - InlineAsm { operands, template: _, options: _, line_spans: _ } => { - for op in operands { + InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { + for op in &**operands { use InlineAsmOperand::*; match op { In { expr, reg: _ } | Out { expr: Some(expr), reg: _, late: _ } | InOut { expr, reg: _, late: _ } - | SymFn { expr } => visitor.visit_expr(expr), + | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]), SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - visitor.visit_expr(in_expr); + visitor.visit_expr(&visitor.thir()[*in_expr]); if let Some(out_expr) = out_expr { - visitor.visit_expr(out_expr); + visitor.visit_expr(&visitor.thir()[*out_expr]); } } Out { expr: None, reg: _, late: _ } @@ -127,24 +128,21 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>( } } ThreadLocalRef(_) => {} - LlvmInlineAsm { outputs, inputs, asm: _ } => { - for out_expr in outputs { - visitor.visit_expr(out_expr); + LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => { + for &out_expr in &**outputs { + visitor.visit_expr(&visitor.thir()[out_expr]); } - for in_expr in inputs { - visitor.visit_expr(in_expr); + for &in_expr in &**inputs { + visitor.visit_expr(&visitor.thir()[in_expr]); } } - Yield { value } => visitor.visit_expr(value), + Yield { value } => visitor.visit_expr(&visitor.thir()[value]), } } -pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>( - visitor: &mut V, - stmt: &'thir Stmt<'thir, 'tcx>, -) { +pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { match stmt.kind { - StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(expr), + StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]), StmtKind::Let { initializer, remainder_scope: _, @@ -153,34 +151,28 @@ pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>( lint_level: _, } => { if let Some(init) = initializer { - visitor.visit_expr(init); + visitor.visit_expr(&visitor.thir()[init]); } } } } -pub fn walk_block<'thir, 'tcx, V: Visitor<'thir, 'tcx>>( - visitor: &mut V, - block: &Block<'thir, 'tcx>, -) { - for stmt in block.stmts { - visitor.visit_stmt(stmt); +pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) { + for &stmt in &*block.stmts { + visitor.visit_stmt(&visitor.thir()[stmt]); } if let Some(expr) = block.expr { - visitor.visit_expr(expr); + visitor.visit_expr(&visitor.thir()[expr]); } } -pub fn walk_arm<'thir, 'tcx, V: Visitor<'thir, 'tcx>>( - visitor: &mut V, - arm: &'thir Arm<'thir, 'tcx>, -) { +pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) { match arm.guard { - Some(Guard::If(expr)) => visitor.visit_expr(expr), + Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), Some(Guard::IfLet(ref _pat, expr)) => { - visitor.visit_expr(expr); + visitor.visit_expr(&visitor.thir()[expr]); } None => {} } - visitor.visit_expr(arm.body); + visitor.visit_expr(&visitor.thir()[arm.body]); }