1
Fork 0

Auto merge of #68804 - ecstatic-morse:qualif-cursor-lazy, r=estebank

Always use lazy qualif getters during const-checking

`has_mut_interior_eager_seek` was needed to work around an overly restrictive bound on the `per_local` argument to the `Qualif` trait. This PR makes that bound `FnMut` instead of `Fn` so we can seek cursors inside of it, resolving a FIXME in the const-checking code.
This commit is contained in:
bors 2020-02-04 10:58:45 +00:00
commit bae3d0dfc7
4 changed files with 35 additions and 52 deletions

View file

@ -34,7 +34,7 @@ pub trait Qualif {
fn in_projection_structurally(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
place: PlaceRef<'_, 'tcx>,
) -> bool {
if let [proj_base @ .., elem] = place.projection {
@ -66,7 +66,7 @@ pub trait Qualif {
fn in_projection(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
place: PlaceRef<'_, 'tcx>,
) -> bool {
Self::in_projection_structurally(cx, per_local, place)
@ -74,7 +74,7 @@ pub trait Qualif {
fn in_place(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
place: PlaceRef<'_, 'tcx>,
) -> bool {
match place {
@ -85,7 +85,7 @@ pub trait Qualif {
fn in_operand(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
operand: &Operand<'tcx>,
) -> bool {
match *operand {
@ -126,7 +126,7 @@ pub trait Qualif {
fn in_rvalue_structurally(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
rvalue: &Rvalue<'tcx>,
) -> bool {
match *rvalue {
@ -170,7 +170,7 @@ pub trait Qualif {
fn in_rvalue(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
rvalue: &Rvalue<'tcx>,
) -> bool {
Self::in_rvalue_structurally(cx, per_local, rvalue)
@ -178,7 +178,7 @@ pub trait Qualif {
fn in_call(
cx: &ConstCx<'_, 'tcx>,
_per_local: &impl Fn(Local) -> bool,
_per_local: &mut impl FnMut(Local) -> bool,
_callee: &Operand<'tcx>,
_args: &[Operand<'tcx>],
return_ty: Ty<'tcx>,
@ -208,7 +208,7 @@ impl Qualif for HasMutInterior {
fn in_rvalue(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
rvalue: &Rvalue<'tcx>,
) -> bool {
match *rvalue {
@ -249,7 +249,7 @@ impl Qualif for NeedsDrop {
fn in_rvalue(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
per_local: &mut impl FnMut(Local) -> bool,
rvalue: &Rvalue<'tcx>,
) -> bool {
if let Rvalue::Aggregate(ref kind, _) = *rvalue {

View file

@ -71,8 +71,13 @@ where
return_place: &mir::Place<'tcx>,
) {
let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty;
let qualif =
Q::in_call(self.item, &|l| self.qualifs_per_local.contains(l), func, args, return_ty);
let qualif = Q::in_call(
self.item,
&mut |l| self.qualifs_per_local.contains(l),
func,
args,
return_ty,
);
if !return_place.is_indirect() {
self.assign_qualif_direct(return_place, qualif);
}
@ -105,7 +110,7 @@ where
rvalue: &mir::Rvalue<'tcx>,
location: Location,
) {
let qualif = Q::in_rvalue(self.item, &|l| self.qualifs_per_local.contains(l), rvalue);
let qualif = Q::in_rvalue(self.item, &mut |l| self.qualifs_per_local.contains(l), rvalue);
if !place.is_indirect() {
self.assign_qualif_direct(place, qualif);
}
@ -120,7 +125,8 @@ where
// here; that occurs in `apply_call_return_effect`.
if let mir::TerminatorKind::DropAndReplace { value, location: dest, .. } = kind {
let qualif = Q::in_operand(self.item, &|l| self.qualifs_per_local.contains(l), value);
let qualif =
Q::in_operand(self.item, &mut |l| self.qualifs_per_local.contains(l), value);
if !dest.is_indirect() {
self.assign_qualif_direct(dest, qualif);
}

View file

@ -64,7 +64,7 @@ impl Qualifs<'a, 'mir, 'tcx> {
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
///
/// Only updates the cursor if absolutely necessary
fn needs_drop_lazy_seek(&mut self, local: Local, location: Location) -> bool {
fn needs_drop(&mut self, local: Local, location: Location) -> bool {
if !self.needs_drop.in_any_value_of_ty.contains(local) {
return false;
}
@ -76,7 +76,7 @@ impl Qualifs<'a, 'mir, 'tcx> {
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
///
/// Only updates the cursor if absolutely necessary.
fn has_mut_interior_lazy_seek(&mut self, local: Local, location: Location) -> bool {
fn has_mut_interior(&mut self, local: Local, location: Location) -> bool {
if !self.has_mut_interior.in_any_value_of_ty.contains(local) {
return false;
}
@ -86,17 +86,6 @@ impl Qualifs<'a, 'mir, 'tcx> {
|| self.indirectly_mutable(local, location)
}
/// Returns `true` if `local` is `HasMutInterior`, but requires the `has_mut_interior` and
/// `indirectly_mutable` cursors to be updated beforehand.
fn has_mut_interior_eager_seek(&self, local: Local) -> bool {
if !self.has_mut_interior.in_any_value_of_ty.contains(local) {
return false;
}
self.has_mut_interior.cursor.get().contains(local)
|| self.indirectly_mutable.get().contains(local)
}
fn in_return_place(&mut self, item: &Item<'_, 'tcx>) -> ConstQualifs {
// Find the `Return` terminator if one exists.
//
@ -120,8 +109,8 @@ impl Qualifs<'a, 'mir, 'tcx> {
let return_loc = item.body.terminator_loc(return_block);
ConstQualifs {
needs_drop: self.needs_drop_lazy_seek(RETURN_PLACE, return_loc),
has_mut_interior: self.has_mut_interior_lazy_seek(RETURN_PLACE, return_loc),
needs_drop: self.needs_drop(RETURN_PLACE, return_loc),
has_mut_interior: self.has_mut_interior(RETURN_PLACE, return_loc),
}
}
}
@ -244,23 +233,6 @@ impl Validator<'a, 'mir, 'tcx> {
self.check_op_spanned(ops::StaticAccess, span)
}
}
fn check_immutable_borrow_like(&mut self, location: Location, place: &Place<'tcx>) {
// FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually
// seek the cursors beforehand.
self.qualifs.has_mut_interior.cursor.seek_before(location);
self.qualifs.indirectly_mutable.seek(location);
let borrowed_place_has_mut_interior = HasMutInterior::in_place(
&self.item,
&|local| self.qualifs.has_mut_interior_eager_seek(local),
place.as_ref(),
);
if borrowed_place_has_mut_interior {
self.check_op(ops::CellBorrow);
}
}
}
impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
@ -366,12 +338,17 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
Rvalue::AddressOf(Mutability::Mut, _) => self.check_op(ops::MutAddressOf),
Rvalue::Ref(_, BorrowKind::Shared, ref place)
| Rvalue::Ref(_, BorrowKind::Shallow, ref place) => {
self.check_immutable_borrow_like(location, place)
}
| Rvalue::Ref(_, BorrowKind::Shallow, ref place)
| Rvalue::AddressOf(Mutability::Not, ref place) => {
let borrowed_place_has_mut_interior = HasMutInterior::in_place(
&self.item,
&mut |local| self.qualifs.has_mut_interior(local, location),
place.as_ref(),
);
Rvalue::AddressOf(Mutability::Not, ref place) => {
self.check_immutable_borrow_like(location, place)
if borrowed_place_has_mut_interior {
self.check_op(ops::CellBorrow);
}
}
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
@ -571,7 +548,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
let needs_drop = if let Some(local) = dropped_place.as_local() {
// Use the span where the local was declared as the span of the drop error.
err_span = self.body.local_decls[local].source_info.span;
self.qualifs.needs_drop_lazy_seek(local, location)
self.qualifs.needs_drop(local, location)
} else {
true
};

View file

@ -407,7 +407,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// FIXME(eddyb) maybe cache this?
fn qualif_local<Q: qualifs::Qualif>(&self, local: Local) -> bool {
let per_local = &|l| self.qualif_local::<Q>(l);
let per_local = &mut |l| self.qualif_local::<Q>(l);
if let TempState::Defined { location: loc, .. } = self.temps[local] {
let num_stmts = self.body[loc.block].statements.len();