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
This commit is contained in:
commit
7357cfbf3d
12 changed files with 177 additions and 19 deletions
|
@ -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));
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue