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]); }