diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-12-13 19:57:09 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-13 19:57:09 +0100 |
| commit | 7357cfbf3d6f0162fbe24fee34e027ecabeb58ca (patch) | |
| tree | 319e1c6cb03f2fa4120fae11d341fba2d9cd2de0 /compiler/rustc_mir_transform/src | |
| parent | aa5b179599427ef233c4e47db8dac6edae22b4f8 (diff) | |
| parent | d6dc9124b7b814c2c5c35aa6295ea5e54071daac (diff) | |
| download | rust-7357cfbf3d6f0162fbe24fee34e027ecabeb58ca.tar.gz rust-7357cfbf3d6f0162fbe24fee34e027ecabeb58ca.zip | |
Rollup merge of #105147 - nbdd0121:inline_const_unsafe, r=oli-obk
Allow unsafe through inline const
Handle similar to closures.
Address https://github.com/rust-lang/rust/pull/104087#issuecomment-1324173328
Note that this PR does not fix the issue for `unsafe { [0; function_requiring_unsafe()] }`. This is fundamentally unfixable for MIR unsafeck IMO.
This PR also does not fix unsafety checking for inline const in pattern position. It actually breaks it, allowing unsafe functions to be used in inline const in pattern position without unsafe blocks. Inline const in pattern position is not visible in MIR so ignored by MIR unsafety checking (currently it is also not checked by borrow checker, which is the reason why it's considered an incomplete feature).
`@rustbot` label: +T-lang +F-inline_const
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/check_unsafety.rs | 35 |
1 files changed, 32 insertions, 3 deletions
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; } |
