Use slice patterns to match projection base
This commit is contained in:
parent
b04e6c7344
commit
e73d189e4e
12 changed files with 66 additions and 117 deletions
|
|
@ -720,12 +720,9 @@ macro_rules! make_mir_visitor {
|
|||
projection: & $($mutability)? [PlaceElem<'tcx>],
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
if !projection.is_empty() {
|
||||
let proj_len = projection.len();
|
||||
let proj_base = & $($mutability)? projection[..proj_len - 1];
|
||||
if let [proj_base @ .., elem] = projection {
|
||||
self.visit_projection(base, proj_base, context, location);
|
||||
|
||||
let elem = & $($mutability)? projection[proj_len - 1];
|
||||
match elem {
|
||||
ProjectionElem::Field(_field, ty) => {
|
||||
self.visit_ty(ty, TyContext::Location(location));
|
||||
|
|
|
|||
|
|
@ -105,10 +105,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
|
|||
) {
|
||||
let cx = self.fx.cx;
|
||||
|
||||
if let [.., elem] = place_ref.projection {
|
||||
// FIXME(spastorino) include this in the pattern when stabilized
|
||||
let proj_base = &place_ref.projection[..place_ref.projection.len() - 1];
|
||||
|
||||
if let [proj_base @ .., elem] = place_ref.projection {
|
||||
// Allow uses of projections that are ZSTs or from scalar fields.
|
||||
let is_consume = match context {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
|
|
|
|||
|
|
@ -514,10 +514,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
},
|
||||
mir::PlaceRef {
|
||||
base,
|
||||
projection: [.., mir::ProjectionElem::Deref],
|
||||
projection: [proj_base @ .., mir::ProjectionElem::Deref],
|
||||
} => {
|
||||
let proj_base = &place_ref.projection[..place_ref.projection.len() - 1];
|
||||
|
||||
// Load the pointer from its location.
|
||||
self.codegen_consume(bx, &mir::PlaceRef {
|
||||
base,
|
||||
|
|
@ -526,10 +524,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
mir::PlaceRef {
|
||||
base,
|
||||
projection: [.., elem],
|
||||
projection: [proj_base @ .., elem],
|
||||
} => {
|
||||
let proj_base = &place_ref.projection[..place_ref.projection.len() - 1];
|
||||
|
||||
// FIXME turn this recursion into iteration
|
||||
let cg_base = self.codegen_place(bx, &mir::PlaceRef {
|
||||
base,
|
||||
|
|
|
|||
|
|
@ -179,10 +179,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
PlaceRef {
|
||||
base,
|
||||
projection: [.., elem],
|
||||
projection: [proj_base @ .., elem],
|
||||
} => {
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let upvar_field_projection =
|
||||
|
|
@ -363,11 +361,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
self.describe_field_from_ty(&static_.ty, field, None),
|
||||
PlaceRef {
|
||||
base,
|
||||
projection: [.., elem],
|
||||
projection: [proj_base @ .., elem],
|
||||
} => match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
|
||||
self.describe_field(PlaceRef {
|
||||
base,
|
||||
projection: proj_base,
|
||||
|
|
@ -384,8 +380,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
ProjectionElem::Index(..)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subslice { .. } => {
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
|
||||
self.describe_field(PlaceRef {
|
||||
base,
|
||||
projection: proj_base,
|
||||
|
|
|
|||
|
|
@ -2187,10 +2187,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
PlaceRef {
|
||||
base: _,
|
||||
projection: [.., elem],
|
||||
projection: [proj_base @ .., elem],
|
||||
} => {
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let base_ty =
|
||||
|
|
|
|||
|
|
@ -305,11 +305,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
|
||||
.find_map(|p| self.is_upvar_field_projection(p));
|
||||
|
||||
let deref_base = match deref_target_place.projection {
|
||||
box [.., ProjectionElem::Deref] => {
|
||||
let proj_base =
|
||||
&deref_target_place.projection[..deref_target_place.projection.len() - 1];
|
||||
|
||||
let deref_base = match &deref_target_place.projection {
|
||||
box [proj_base @ .., ProjectionElem::Deref] => {
|
||||
PlaceRef {
|
||||
base: &deref_target_place.base,
|
||||
projection: proj_base,
|
||||
|
|
|
|||
|
|
@ -65,10 +65,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
PlaceRef {
|
||||
base: _,
|
||||
projection: [.., ProjectionElem::Field(upvar_index, _)],
|
||||
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
|
||||
} => {
|
||||
let proj_base = &the_place_err.projection[..the_place_err.projection.len() - 1];
|
||||
|
||||
debug_assert!(is_closure_or_generator(
|
||||
Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty
|
||||
));
|
||||
|
|
@ -329,10 +327,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// Also suggest adding mut for upvars
|
||||
PlaceRef {
|
||||
base,
|
||||
projection: [.., ProjectionElem::Field(upvar_index, _)],
|
||||
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
|
||||
} => {
|
||||
let proj_base = &the_place_err.projection[..the_place_err.projection.len() - 1];
|
||||
|
||||
debug_assert!(is_closure_or_generator(
|
||||
Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty
|
||||
));
|
||||
|
|
|
|||
|
|
@ -88,10 +88,8 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
|
|||
}
|
||||
PlaceRef {
|
||||
base: _,
|
||||
projection: [.., elem],
|
||||
projection: [proj_base @ .., elem],
|
||||
} => {
|
||||
let proj_base = &cursor.projection[..cursor.projection.len() - 1];
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
|
||||
// FIXME: add union handling
|
||||
|
|
|
|||
|
|
@ -436,8 +436,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
|
||||
// Check if we are assigning into a field of a union, if so, lookup the place
|
||||
// of the union so it is marked as initialized again.
|
||||
if let [.., ProjectionElem::Field(_, _)] = place.projection {
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection {
|
||||
if let ty::Adt(def, _) =
|
||||
Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.sty
|
||||
{
|
||||
|
|
|
|||
|
|
@ -90,20 +90,11 @@ impl OptimizationFinder<'b, 'tcx> {
|
|||
impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
|
||||
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
if let Rvalue::Ref(_, _, Place {
|
||||
base: _,
|
||||
projection: box [.., elem],
|
||||
base,
|
||||
projection: box [proj_base @ .., ProjectionElem::Deref],
|
||||
}) = rvalue {
|
||||
if *elem == ProjectionElem::Deref {
|
||||
// FIXME remove this once we can use slices patterns
|
||||
if let Rvalue::Ref(_, _, Place {
|
||||
base,
|
||||
projection,
|
||||
}) = rvalue {
|
||||
let proj_base = &projection[..projection.len() - 1];
|
||||
if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
|
||||
self.optimizations.and_stars.insert(location);
|
||||
}
|
||||
}
|
||||
if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
|
||||
self.optimizations.and_stars.insert(location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,27 +187,28 @@ trait Qualif {
|
|||
cx: &ConstCx<'_, 'tcx>,
|
||||
place: PlaceRef<'_, 'tcx>,
|
||||
) -> bool {
|
||||
let elem = &place.projection[place.projection.len() - 1];
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
if let [proj_base @ .., elem] = place.projection {
|
||||
let base_qualif = Self::in_place(cx, PlaceRef {
|
||||
base: place.base,
|
||||
projection: proj_base,
|
||||
});
|
||||
let qualif = base_qualif && Self::mask_for_ty(
|
||||
cx,
|
||||
Place::ty_from(place.base, proj_base, cx.body, cx.tcx)
|
||||
.projection_ty(cx.tcx, elem)
|
||||
.ty,
|
||||
);
|
||||
match elem {
|
||||
ProjectionElem::Deref |
|
||||
ProjectionElem::Subslice { .. } |
|
||||
ProjectionElem::Field(..) |
|
||||
ProjectionElem::ConstantIndex { .. } |
|
||||
ProjectionElem::Downcast(..) => qualif,
|
||||
|
||||
let base_qualif = Self::in_place(cx, PlaceRef {
|
||||
base: place.base,
|
||||
projection: proj_base,
|
||||
});
|
||||
let qualif = base_qualif && Self::mask_for_ty(
|
||||
cx,
|
||||
Place::ty_from(place.base, proj_base, cx.body, cx.tcx)
|
||||
.projection_ty(cx.tcx, elem)
|
||||
.ty,
|
||||
);
|
||||
match elem {
|
||||
ProjectionElem::Deref |
|
||||
ProjectionElem::Subslice { .. } |
|
||||
ProjectionElem::Field(..) |
|
||||
ProjectionElem::ConstantIndex { .. } |
|
||||
ProjectionElem::Downcast(..) => qualif,
|
||||
|
||||
ProjectionElem::Index(local) => qualif || Self::in_local(cx, *local),
|
||||
ProjectionElem::Index(local) => qualif || Self::in_local(cx, *local),
|
||||
}
|
||||
} else {
|
||||
bug!("This should be called if projection is not empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -290,10 +291,7 @@ trait Qualif {
|
|||
|
||||
Rvalue::Ref(_, _, ref place) => {
|
||||
// Special-case reborrows to be more like a copy of the reference.
|
||||
if !place.projection.is_empty() {
|
||||
let elem = &place.projection[place.projection.len() - 1];
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
|
||||
if let box [proj_base @ .., elem] = &place.projection {
|
||||
if ProjectionElem::Deref == *elem {
|
||||
let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.sty {
|
||||
|
|
@ -457,31 +455,32 @@ impl Qualif for IsNotPromotable {
|
|||
cx: &ConstCx<'_, 'tcx>,
|
||||
place: PlaceRef<'_, 'tcx>,
|
||||
) -> bool {
|
||||
let elem = &place.projection[place.projection.len() - 1];
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
if let [proj_base @ .., elem] = place.projection {
|
||||
match elem {
|
||||
ProjectionElem::Deref |
|
||||
ProjectionElem::Downcast(..) => return true,
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref |
|
||||
ProjectionElem::Downcast(..) => return true,
|
||||
ProjectionElem::ConstantIndex {..} |
|
||||
ProjectionElem::Subslice {..} |
|
||||
ProjectionElem::Index(_) => {}
|
||||
|
||||
ProjectionElem::ConstantIndex {..} |
|
||||
ProjectionElem::Subslice {..} |
|
||||
ProjectionElem::Index(_) => {}
|
||||
|
||||
ProjectionElem::Field(..) => {
|
||||
if cx.mode == Mode::NonConstFn {
|
||||
let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
// No promotion of union field accesses.
|
||||
if def.is_union() {
|
||||
return true;
|
||||
ProjectionElem::Field(..) => {
|
||||
if cx.mode == Mode::NonConstFn {
|
||||
let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
// No promotion of union field accesses.
|
||||
if def.is_union() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self::in_projection_structurally(cx, place)
|
||||
Self::in_projection_structurally(cx, place)
|
||||
} else {
|
||||
bug!("This should be called if projection is not empty");
|
||||
}
|
||||
}
|
||||
|
||||
fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool {
|
||||
|
|
@ -866,14 +865,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
|||
// projections are transparent for assignments
|
||||
// we qualify the entire destination at once, even if just a field would have
|
||||
// stricter qualification
|
||||
(base, proj @ [.., _]) => {
|
||||
let proj_base = &proj[..proj.len() - 1];
|
||||
|
||||
(base, [proj_base @ .., _]) => {
|
||||
// Catch more errors in the destination. `visit_place` also checks various
|
||||
// projection rules like union field access and raw pointer deref
|
||||
let context = PlaceContext::MutatingUse(MutatingUseContext::Store);
|
||||
self.visit_place_base(base, context, location);
|
||||
self.visit_projection(base, proj, context, location);
|
||||
self.visit_projection(base, dest_projection, context, location);
|
||||
dest_projection = proj_base;
|
||||
},
|
||||
(&PlaceBase::Static(box Static {
|
||||
|
|
@ -1096,10 +1093,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
);
|
||||
self.super_projection(place_base, proj, context, location);
|
||||
|
||||
if !proj.is_empty() {
|
||||
let elem = &proj[proj.len() - 1];
|
||||
let proj_base = &proj[..proj.len() - 1];
|
||||
|
||||
if let [proj_base @ .., elem] = proj {
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
if context.is_mutating_use() {
|
||||
|
|
@ -1187,9 +1181,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
if let Rvalue::Ref(_, kind, ref place) = *rvalue {
|
||||
// Special-case reborrows.
|
||||
let mut reborrow_place = None;
|
||||
if let box [.., elem] = &place.projection {
|
||||
if let box [proj_base @ .., elem] = &place.projection {
|
||||
if *elem == ProjectionElem::Deref {
|
||||
let proj_base = &place.projection[..place.projection.len() - 1];
|
||||
let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.sty {
|
||||
reborrow_place = Some(proj_base);
|
||||
|
|
|
|||
|
|
@ -61,9 +61,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
|
|||
rvalue: &Rvalue<'tcx>,
|
||||
location: Location) {
|
||||
if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue {
|
||||
if let box [.., elem] = &src_place.projection {
|
||||
let proj_base = &src_place.projection[..src_place.projection.len() - 1];
|
||||
|
||||
if let box [proj_base @ .., elem] = &src_place.projection {
|
||||
if let ProjectionElem::ConstantIndex{offset: _,
|
||||
min_length: _,
|
||||
from_end: false} = elem {
|
||||
|
|
@ -102,10 +100,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
|
|||
proj: &[PlaceElem<'tcx>],
|
||||
item_ty: &'tcx ty::TyS<'tcx>,
|
||||
size: u32) {
|
||||
if !proj.is_empty() {
|
||||
let elem = &proj[proj.len() - 1];
|
||||
let proj_base = &proj[..proj.len() - 1];
|
||||
|
||||
if let [proj_base @ .., elem] = proj {
|
||||
match elem {
|
||||
// uniforms statements like_10 = move _2[:-1];
|
||||
ProjectionElem::Subslice{from, to} => {
|
||||
|
|
@ -314,11 +309,9 @@ impl RestoreSubsliceArrayMoveOut {
|
|||
_,
|
||||
box Rvalue::Use(Operand::Move(Place {
|
||||
base,
|
||||
projection,
|
||||
projection: box [proj_base @ .., _],
|
||||
})),
|
||||
) = &statement.kind {
|
||||
let proj_base = &projection[..projection.len() - 1];
|
||||
|
||||
) = &statement.kind {
|
||||
return Some((*offset, PlaceRef {
|
||||
base,
|
||||
projection: proj_base,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue