use PlaceRef abstractions

This commit is contained in:
Eric Mark Martin 2023-06-19 03:44:04 -04:00
parent 06b444b2d1
commit 66590ba41b
2 changed files with 7 additions and 15 deletions

View file

@ -320,8 +320,6 @@ fn base_local_and_movability<'tcx>(
mir: &mir::Body<'tcx>, mir: &mir::Body<'tcx>,
place: mir::Place<'tcx>, place: mir::Place<'tcx>,
) -> (mir::Local, CannotMoveOut) { ) -> (mir::Local, CannotMoveOut) {
use rustc_middle::mir::PlaceRef;
// Dereference. You cannot move things out from a borrowed value. // Dereference. You cannot move things out from a borrowed value.
let mut deref = false; let mut deref = false;
// Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509. // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
@ -330,17 +328,14 @@ fn base_local_and_movability<'tcx>(
// underlying type implements Copy // underlying type implements Copy
let mut slice = false; let mut slice = false;
let PlaceRef { local, mut projection } = place.as_ref(); for (base, elem) in place.as_ref().iter_projections() {
while let [base @ .., elem] = projection { let base_ty = base.ty(&mir.local_decls, cx.tcx).ty;
projection = base;
deref |= matches!(elem, mir::ProjectionElem::Deref); deref |= matches!(elem, mir::ProjectionElem::Deref);
field |= matches!(elem, mir::ProjectionElem::Field(..)) field |= matches!(elem, mir::ProjectionElem::Field(..)) && has_drop(cx, base_ty);
&& has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); slice |= matches!(elem, mir::ProjectionElem::Index(..)) && !is_copy(cx, base_ty);
slice |= matches!(elem, mir::ProjectionElem::Index(..))
&& !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
} }
(local, deref || field || slice) (place.local, deref || field || slice)
} }
#[derive(Default)] #[derive(Default)]

View file

@ -284,13 +284,10 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
} }
fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
let mut cursor = place.projection.as_ref(); for (base, elem) in place.as_ref().iter_projections() {
while let [ref proj_base @ .., elem] = *cursor {
cursor = proj_base;
match elem { match elem {
ProjectionElem::Field(..) => { ProjectionElem::Field(..) => {
let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; let base_ty = base.ty(body, tcx).ty;
if let Some(def) = base_ty.ty_adt_def() { if let Some(def) = base_ty.ty_adt_def() {
// No union field accesses in `const fn` // No union field accesses in `const fn`
if def.is_union() { if def.is_union() {