Use slice patterns to match projection base

上级 b04e6c73
......@@ -720,12 +720,9 @@ fn super_projection(&mut self,
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 @@ fn process_place(
) {
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 @@ pub fn codegen_place(
},
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 @@ pub fn codegen_place(
}
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 @@ fn append_place_to_string(
}
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 @@ fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
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 @@ fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
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 @@ fn is_mutable<'d>(
}
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 @@ fn report_cannot_move_from_borrowed_content(
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 @@ pub(super) fn report_mutability_error(
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 @@ pub(super) fn report_mutability_error(
// 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 @@ fn next(&mut self) -> Option<Self::Item> {
}
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 @@ fn gather_init(&mut self, place: PlaceRef<'cx, 'tcx>, kind: InitKind) {
// 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 @@ fn new(body: &'b Body<'tcx>, tcx: TyCtxt<'tcx>) -> 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 @@ fn in_projection_structurally(
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 @@ fn in_rvalue_structurally(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool
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 @@ fn in_projection(
cx: &ConstCx<'_, 'tcx>,
place: PlaceRef<'_, 'tcx>,
) -> bool {
let elem = &place.projection[place.projection.len() - 1];
let proj_base = &place.projection[..place.projection.len() - 1];
match elem {
ProjectionElem::Deref |
ProjectionElem::Downcast(..) => return true,
ProjectionElem::ConstantIndex {..} |
ProjectionElem::Subslice {..} |
ProjectionElem::Index(_) => {}
if let [proj_base @ .., elem] = place.projection {
match elem {
ProjectionElem::Deref |
ProjectionElem::Downcast(..) => 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;
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;
}
}
}
}
}
}
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 @@ fn assign(&mut self, dest: &Place<'tcx>, source: ValueSource<'_, 'tcx>, location
// 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 @@ fn visit_projection(
);
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 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
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 @@ fn visit_assign(&mut self,
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 @@ fn uniform(&mut self,
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 @@ fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse,
_,
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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册