summaryrefslogtreecommitdiff
path: root/compiler/rustc_mir_dataflow
diff options
context:
space:
mode:
authorclubby789 <jamie@hill-daniel.co.uk>2023-03-17 12:26:04 +0000
committerclubby789 <jamie@hill-daniel.co.uk>2023-03-17 12:26:04 +0000
commitce2d52841b30616b3258685439ab13b03520ae10 (patch)
treedd518823267c4ad29b1c90570f38819ce94bfb6b /compiler/rustc_mir_dataflow
parent2d64f229a09515978e6f338b821057a64334a0b5 (diff)
downloadrust-ce2d52841b30616b3258685439ab13b03520ae10.tar.gz
Drop subslices of arrays
Diffstat (limited to 'compiler/rustc_mir_dataflow')
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs72
1 files changed, 54 insertions, 18 deletions
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 486275570bd..be6eab107a4 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -729,23 +729,59 @@ where
let tcx = self.tcx();
if let Some(size) = opt_size {
- let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size)
- .map(|i| {
- (
- tcx.mk_place_elem(
- self.place,
- ProjectionElem::ConstantIndex {
- offset: i,
- min_length: size,
- from_end: false,
- },
- ),
- self.elaborator.array_subpath(self.path, i, size),
- )
- })
- .collect();
-
- if fields.iter().any(|(_, path)| path.is_some()) {
+ enum ProjectionKind<Path> {
+ Drop(std::ops::Range<u64>),
+ Keep(u64, Path),
+ }
+ // Previously, we'd make a projection for every element in the array and create a drop
+ // ladder if any `array_subpath` was `Some`, i.e. moving out with an array pattern.
+ // This caused huge memory usage when generating the drops for large arrays, so we instead
+ // record the *subslices* which are dropped and the *indexes* which are kept
+ let mut drop_ranges = vec![];
+ let mut dropping = true;
+ let mut start = 0;
+ for i in 0..size {
+ let path = self.elaborator.array_subpath(self.path, i, size);
+ if dropping && path.is_some() {
+ drop_ranges.push(ProjectionKind::Drop(start..i));
+ dropping = false;
+ } else if !dropping && path.is_none() {
+ dropping = true;
+ start = i;
+ }
+ if let Some(path) = path {
+ drop_ranges.push(ProjectionKind::Keep(i, path));
+ }
+ }
+ if !drop_ranges.is_empty() {
+ if dropping {
+ drop_ranges.push(ProjectionKind::Drop(start..size));
+ }
+ let fields = drop_ranges
+ .iter()
+ .rev()
+ .map(|p| {
+ let (project, path) = match p {
+ ProjectionKind::Drop(r) => (
+ ProjectionElem::Subslice {
+ from: r.start,
+ to: r.end,
+ from_end: false,
+ },
+ None,
+ ),
+ &ProjectionKind::Keep(offset, path) => (
+ ProjectionElem::ConstantIndex {
+ offset,
+ min_length: size,
+ from_end: false,
+ },
+ Some(path),
+ ),
+ };
+ (tcx.mk_place_elem(self.place, project), path)
+ })
+ .collect::<Vec<_>>();
let (succ, unwind) = self.drop_ladder_bottom();
return self.drop_ladder(fields, succ, unwind).0;
}
@@ -824,7 +860,7 @@ where
let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
self.open_drop_for_array(*ety, size)
}
- ty::Slice(ety) => self.open_drop_for_array(*ety, None),
+ ty::Slice(ety) => self.drop_loop_pair(*ety),
_ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
}