Lazily run dataflow for const qualification
This commit is contained in:
parent
274c85f5c8
commit
1343797859
1 changed files with 56 additions and 43 deletions
|
@ -33,34 +33,64 @@ type IndirectlyMutableResults<'mir, 'tcx> =
|
||||||
type QualifResults<'mir, 'tcx, Q> =
|
type QualifResults<'mir, 'tcx, Q> =
|
||||||
dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Qualifs<'mir, 'tcx> {
|
pub struct Qualifs<'mir, 'tcx> {
|
||||||
has_mut_interior: QualifResults<'mir, 'tcx, HasMutInterior>,
|
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
|
||||||
needs_drop: QualifResults<'mir, 'tcx, NeedsDrop>,
|
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
|
||||||
indirectly_mutable: IndirectlyMutableResults<'mir, 'tcx>,
|
indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Qualifs<'mir, 'tcx> {
|
impl Qualifs<'mir, 'tcx> {
|
||||||
fn indirectly_mutable(
|
fn indirectly_mutable(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &Item<'mir, 'tcx>,
|
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||||
local: Local,
|
local: Local,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.indirectly_mutable.seek_before(location);
|
let indirectly_mutable = self.indirectly_mutable.get_or_insert_with(|| {
|
||||||
self.indirectly_mutable.get().contains(local)
|
let ConstCx { tcx, body, def_id, param_env, .. } = *ccx;
|
||||||
|
|
||||||
|
// We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
|
||||||
|
// allowed in a const.
|
||||||
|
//
|
||||||
|
// FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
|
||||||
|
// without breaking stable code?
|
||||||
|
MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
|
||||||
|
.unsound_ignore_borrow_on_drop()
|
||||||
|
.into_engine(tcx, &body, def_id)
|
||||||
|
.iterate_to_fixpoint()
|
||||||
|
.into_results_cursor(&body)
|
||||||
|
});
|
||||||
|
|
||||||
|
indirectly_mutable.seek_before(location);
|
||||||
|
indirectly_mutable.get().contains(local)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
|
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
|
||||||
///
|
///
|
||||||
/// Only updates the cursor if absolutely necessary
|
/// Only updates the cursor if absolutely necessary
|
||||||
fn needs_drop(&mut self, item: &Item<'mir, 'tcx>, local: Local, location: Location) -> bool {
|
fn needs_drop(
|
||||||
let ty = item.body.local_decls[local].ty;
|
&mut self,
|
||||||
if !NeedsDrop::in_any_value_of_ty(item, ty) {
|
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||||
|
local: Local,
|
||||||
|
location: Location,
|
||||||
|
) -> bool {
|
||||||
|
let ty = ccx.body.local_decls[local].ty;
|
||||||
|
if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.needs_drop.seek_before(location);
|
let needs_drop = self.needs_drop.get_or_insert_with(|| {
|
||||||
self.needs_drop.get().contains(local) || self.indirectly_mutable(item, local, location)
|
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
||||||
|
|
||||||
|
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
|
||||||
|
.into_engine(tcx, &body, def_id)
|
||||||
|
.iterate_to_fixpoint()
|
||||||
|
.into_results_cursor(&body)
|
||||||
|
});
|
||||||
|
|
||||||
|
needs_drop.seek_before(location);
|
||||||
|
needs_drop.get().contains(local) || self.indirectly_mutable(ccx, local, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
|
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
|
||||||
|
@ -68,7 +98,7 @@ impl Qualifs<'mir, 'tcx> {
|
||||||
/// Only updates the cursor if absolutely necessary.
|
/// Only updates the cursor if absolutely necessary.
|
||||||
fn has_mut_interior(
|
fn has_mut_interior(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: &Item<'mir, 'tcx>,
|
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||||
local: Local,
|
local: Local,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -77,12 +107,20 @@ impl Qualifs<'mir, 'tcx> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.has_mut_interior.seek_before(location);
|
let has_mut_interior = self.has_mut_interior.get_or_insert_with(|| {
|
||||||
self.has_mut_interior.get().contains(local)
|
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
||||||
|| self.indirectly_mutable(item, local, location)
|
|
||||||
|
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
|
||||||
|
.into_engine(tcx, &body, def_id)
|
||||||
|
.iterate_to_fixpoint()
|
||||||
|
.into_results_cursor(&body)
|
||||||
|
});
|
||||||
|
|
||||||
|
has_mut_interior.seek_before(location);
|
||||||
|
has_mut_interior.get().contains(local) || self.indirectly_mutable(ccx, local, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_return_place(&mut self, item: &Item<'mir, 'tcx>) -> ConstQualifs {
|
fn in_return_place(&mut self, ccx: &'mir ConstCx<'mir, 'tcx>) -> ConstQualifs {
|
||||||
// Find the `Return` terminator if one exists.
|
// Find the `Return` terminator if one exists.
|
||||||
//
|
//
|
||||||
// If no `Return` terminator exists, this MIR is divergent. Just return the conservative
|
// If no `Return` terminator exists, this MIR is divergent. Just return the conservative
|
||||||
|
@ -128,33 +166,8 @@ impl Deref for Validator<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validator<'mir, 'tcx> {
|
impl Validator<'mir, 'tcx> {
|
||||||
pub fn new(item: &'mir Item<'mir, 'tcx>) -> Self {
|
pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
|
||||||
let Item { tcx, body, def_id, param_env, .. } = *item;
|
Validator { span: ccx.body.span, ccx, qualifs: Default::default() }
|
||||||
|
|
||||||
// We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
|
|
||||||
// allowed in a const.
|
|
||||||
//
|
|
||||||
// FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
|
|
||||||
// without breaking stable code?
|
|
||||||
let indirectly_mutable = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env)
|
|
||||||
.unsound_ignore_borrow_on_drop()
|
|
||||||
.into_engine(tcx, body, def_id)
|
|
||||||
.iterate_to_fixpoint()
|
|
||||||
.into_results_cursor(body);
|
|
||||||
|
|
||||||
let needs_drop = FlowSensitiveAnalysis::new(NeedsDrop, item)
|
|
||||||
.into_engine(item.tcx, &item.body, item.def_id)
|
|
||||||
.iterate_to_fixpoint()
|
|
||||||
.into_results_cursor(*item.body);
|
|
||||||
|
|
||||||
let has_mut_interior = FlowSensitiveAnalysis::new(HasMutInterior, item)
|
|
||||||
.into_engine(item.tcx, &item.body, item.def_id)
|
|
||||||
.iterate_to_fixpoint()
|
|
||||||
.into_results_cursor(*item.body);
|
|
||||||
|
|
||||||
let qualifs = Qualifs { needs_drop, has_mut_interior, indirectly_mutable };
|
|
||||||
|
|
||||||
Validator { span: ccx.body.span, ccx, qualifs }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_body(&mut self) {
|
pub fn check_body(&mut self) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue