Allow unsafe through inline const

This is handled similar to closures
This commit is contained in:
Gary Guo 2022-12-01 18:34:59 +00:00
parent 37d7de3379
commit 9342d1e73e

View File

@ -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;
}