Make closures inherit their parent's "safety context"

This commit is contained in:
LeSeulArtichaut 2021-05-23 18:10:32 +02:00
parent 8d1e3d3b74
commit 6c4f40dee1

View file

@ -213,6 +213,30 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
self.requires_unsafe(expr.span, CastOfPointerToInt);
}
}
ExprKind::Closure {
closure_id,
substs: _,
upvars: _,
movability: _,
fake_reads: _,
} => {
let closure_id = closure_id.expect_local();
let closure_def = if let Some((did, const_param_id)) =
ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
{
ty::WithOptConstParam { did, const_param_did: Some(const_param_id) }
} else {
ty::WithOptConstParam::unknown(closure_id)
};
let (closure_thir, expr) = self.tcx.thir_body(closure_def);
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;
}
_ => {}
}
@ -335,14 +359,18 @@ 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>, def: ty::WithOptConstParam<LocalDefId>) {
// THIR unsafeck is gated under `-Z thir-unsafeck`
if !tcx.sess.opts.debugging_opts.thir_unsafeck {
return;
}
// Closures are handled by their parent function
if tcx.is_closure(def.did.to_def_id()) {
tcx.ensure().thir_check_unsafety(tcx.hir().local_def_id_to_hir_id(def.did).owner);
return;
}
let (thir, expr) = tcx.thir_body(def);
let thir = &thir.borrow();
// If `thir` is empty, a type error occured, skip this body.