Auto merge of #66650 - matthewjasper:nonuniform-array-move, r=pnkfelix

Remove uniform array move MIR passes

This PR fixes a number of bugs caused by limitations of this pass

* Projections from constant indexes weren't being canonicalized
* Constant indexes from the start weren't being canonicalized (they could have different min_lengths)
* It didn't apply to non-moves

This PR makes the following changes to support removing this pass:

* ConstantIndex of arrays are now generated in a canonical form (from the start, min_length is the actual length).
* Subslices are now split when generating move paths and when checking subslices have been moved.

Additionally

* The parent move path of a projection from an array element is now calculated correctly

closes #66502
This commit is contained in:
bors 2019-12-11 23:00:38 +00:00
commit de0abf7599
32 changed files with 1141 additions and 641 deletions

View file

@ -1714,18 +1714,25 @@ pub enum ProjectionElem<V, T> {
ConstantIndex {
/// index or -index (in Python terms), depending on from_end
offset: u32,
/// thing being indexed must be at least this long
/// The thing being indexed must be at least this long. For arrays this
/// is always the exact length.
min_length: u32,
/// counting backwards from end?
/// Counting backwards from end? This is always false when indexing an
/// array.
from_end: bool,
},
/// These indices are generated by slice patterns.
///
/// slice[from:-to] in Python terms.
/// If `from_end` is true `slice[from..slice.len() - to]`.
/// Otherwise `array[from..to]`.
Subslice {
from: u32,
to: u32,
/// Whether `to` counts from the start or end of the array/slice.
/// For `PlaceElem`s this is `true` if and only if the base is a slice.
/// For `ProjectionKind`, this can also be `true` for arrays.
from_end: bool,
},
/// "Downcast" to a variant of an ADT. Currently, we only introduce
@ -1914,15 +1921,18 @@ impl Debug for Place<'_> {
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
}
ProjectionElem::Subslice { from, to } if *to == 0 => {
ProjectionElem::Subslice { from, to, from_end: true } if *to == 0 => {
write!(fmt, "[{:?}:]", from)?;
}
ProjectionElem::Subslice { from, to } if *from == 0 => {
ProjectionElem::Subslice { from, to, from_end: true } if *from == 0 => {
write!(fmt, "[:-{:?}]", to)?;
}
ProjectionElem::Subslice { from, to } => {
ProjectionElem::Subslice { from, to, from_end: true } => {
write!(fmt, "[{:?}:-{:?}]", from, to)?;
}
ProjectionElem::Subslice { from, to, from_end: false } => {
write!(fmt, "[{:?}..{:?}]", from, to)?;
}
}
}
@ -2456,7 +2466,7 @@ impl UserTypeProjection {
}
pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
self.projs.push(ProjectionElem::Subslice { from, to });
self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
self
}

View file

@ -88,14 +88,17 @@ impl<'tcx> PlaceTy<'tcx> {
}
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
PlaceTy::from_ty(self.ty.builtin_index().unwrap()),
ProjectionElem::Subslice { from, to } => {
ProjectionElem::Subslice { from, to, from_end } => {
PlaceTy::from_ty(match self.ty.kind {
ty::Array(inner, size) => {
ty::Slice(..) => self.ty,
ty::Array(inner, _) if !from_end => {
tcx.mk_array(inner, (to - from) as u64)
}
ty::Array(inner, size) if from_end => {
let size = size.eval_usize(tcx, param_env);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
}
ty::Slice(..) => self.ty,
_ => {
bug!("cannot subslice non-array type: `{:?}`", self)
}

View file

@ -954,7 +954,7 @@ macro_rules! visit_place_fns {
);
}
ProjectionElem::Deref |
ProjectionElem::Subslice { from: _, to: _ } |
ProjectionElem::Subslice { from: _, to: _, from_end: _ } |
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
from_end: _ } |