diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_mir_build/src/build/custom/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/mod.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/check_unsafety.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/check_unsafety.rs | 35 |
4 files changed, 58 insertions, 19 deletions
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index eb021f47757..1fd2e40c187 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -20,6 +20,7 @@ use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; +use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_middle::{ mir::*, @@ -33,6 +34,7 @@ mod parse; pub(super) fn build_custom_mir<'tcx>( tcx: TyCtxt<'tcx>, did: DefId, + hir_id: HirId, thir: &Thir<'tcx>, expr: ExprId, params: &IndexVec<ParamId, Param<'tcx>>, @@ -67,7 +69,10 @@ pub(super) fn build_custom_mir<'tcx>( parent_scope: None, inlined: None, inlined_parent_scope: None, - local_data: ClearCrossCrate::Clear, + local_data: ClearCrossCrate::Set(SourceScopeLocalData { + lint_root: hir_id, + safety: Safety::Safe, + }), }); body.injection_phase = Some(parse_attribute(attr)); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 007f3b55ec8..7af89dd472f 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -487,6 +487,7 @@ fn construct_fn<'tcx>( return custom::build_custom_mir( tcx, fn_def.did.to_def_id(), + fn_id, thir, expr, arguments, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index fb1ea9ed300..3bb1f51650a 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -132,6 +132,18 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool { self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow } + + /// Handle closures/generators/inline-consts, which is unsafecked with their parent body. + fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) { + if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) { + let inner_thir = &inner_thir.borrow(); + let hir_context = self.tcx.hir().local_def_id_to_hir_id(def.did); + let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self }; + inner_visitor.visit_expr(&inner_thir[expr]); + // Unsafe blocks can be used in the inner body, make sure to take it into account + self.safety_context = inner_visitor.safety_context; + } + } } // Searches for accesses to layout constrained fields. @@ -408,16 +420,11 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } else { ty::WithOptConstParam::unknown(closure_id) }; - let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| { - (self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)) - }); - let closure_thir = &closure_thir.borrow(); - let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id); - let mut closure_visitor = - UnsafetyVisitor { thir: closure_thir, hir_context, ..*self }; - closure_visitor.visit_expr(&closure_thir[expr]); - // Unsafe blocks can be used in closures, make sure to take it into account - self.safety_context = closure_visitor.safety_context; + self.visit_inner_body(closure_def); + } + ExprKind::ConstBlock { did, substs: _ } => { + let def_id = did.expect_local(); + self.visit_inner_body(ty::WithOptConstParam::unknown(def_id)); } ExprKind::Field { lhs, .. } => { let lhs = &self.thir[lhs]; @@ -612,11 +619,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD return; } - // Closures are handled by their owner, if it has a body - if tcx.is_closure(def.did.to_def_id()) { - let hir = tcx.hir(); - let owner = hir.enclosing_body_owner(hir.local_def_id_to_hir_id(def.did)); - tcx.ensure().thir_check_unsafety(owner); + // Closures and inline consts are handled by their owner, if it has a body + if tcx.is_typeck_child(def.did.to_def_id()) { return; } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index e783d189137..782abd7804d 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::HirId; use rustc_hir::intravisit; @@ -134,6 +135,28 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { self.super_rvalue(rvalue, location); } + fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) { + if let Operand::Constant(constant) = op { + let maybe_uneval = match constant.literal { + ConstantKind::Val(..) | ConstantKind::Ty(_) => None, + ConstantKind::Unevaluated(uv, _) => Some(uv), + }; + + if let Some(uv) = maybe_uneval { + if uv.promoted.is_none() { + let def_id = uv.def.def_id_for_type_of(); + if self.tcx.def_kind(def_id) == DefKind::InlineConst { + let local_def_id = def_id.expect_local(); + let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = + self.tcx.unsafety_check_result(local_def_id); + self.register_violations(violations, used_unsafe_blocks.iter().copied()); + } + } + } + } + self.super_operand(op, location); + } + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { // On types with `scalar_valid_range`, prevent // * `&mut x.field` @@ -410,6 +433,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { intravisit::walk_block(self, block); } + fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + if matches!(self.tcx.def_kind(c.def_id), DefKind::InlineConst) { + self.visit_body(self.tcx.hir().body(c.body)) + } + } + fn visit_fn( &mut self, fk: intravisit::FnKind<'tcx>, @@ -484,7 +513,7 @@ fn unsafety_check_result<'tcx>( let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env); checker.visit_body(&body); - let unused_unsafes = (!tcx.is_closure(def.did.to_def_id())) + let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id())) .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks)); tcx.arena.alloc(UnsafetyCheckResult { @@ -516,8 +545,8 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { debug!("check_unsafety({:?})", def_id); - // closures are handled by their parent fn. - if tcx.is_closure(def_id.to_def_id()) { + // closures and inline consts are handled by their parent fn. + if tcx.is_typeck_child(def_id.to_def_id()) { return; } |
