diff options
Diffstat (limited to 'compiler/rustc_mir_dataflow/src')
12 files changed, 174 insertions, 200 deletions
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index bd1208762..bd8ec82df 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -7,7 +7,7 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use std::{fmt, iter}; /// The value of an inserted drop flag. @@ -77,10 +77,10 @@ impl Unwind { } } - fn into_option(self) -> Option<BasicBlock> { + fn into_action(self) -> UnwindAction { match self { - Unwind::To(bb) => Some(bb), - Unwind::InCleanup => None, + Unwind::To(bb) => UnwindAction::Cleanup(bb), + Unwind::InCleanup => UnwindAction::Terminate, } } @@ -129,7 +129,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug { /// Returns the subpath of a field of `path` (or `None` if there is no dedicated subpath). /// /// If this returns `None`, `field` will not get a dedicated drop flag. - fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>; + fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option<Self::Path>; /// Returns the subpath of a dereference of `path` (or `None` if there is no dedicated subpath). /// @@ -236,7 +236,7 @@ where TerminatorKind::Drop { place: self.place, target: self.succ, - unwind: self.unwind.into_option(), + unwind: self.unwind.into_action(), }, ); } @@ -269,7 +269,7 @@ where .iter() .enumerate() .map(|(i, f)| { - let field = Field::new(i); + let field = FieldIdx::new(i); let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); @@ -397,8 +397,8 @@ where .enumerate() .map(|(i, &ty)| { ( - self.tcx().mk_place_field(self.place, Field::new(i), ty), - self.elaborator.field_subpath(self.path, Field::new(i)), + self.tcx().mk_place_field(self.place, FieldIdx::new(i), ty), + self.elaborator.field_subpath(self.path, FieldIdx::new(i)), ) }) .collect(); @@ -411,14 +411,14 @@ where fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock { // drop glue is sent straight to codegen // box cannot be directly dereferenced - let unique_ty = adt.non_enum_variant().fields[0].ty(self.tcx(), substs); - let nonnull_ty = - unique_ty.ty_adt_def().unwrap().non_enum_variant().fields[0].ty(self.tcx(), substs); + let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), substs); + let unique_variant = unique_ty.ty_adt_def().unwrap().non_enum_variant(); + let nonnull_ty = unique_variant.fields[FieldIdx::from_u32(0)].ty(self.tcx(), substs); let ptr_ty = self.tcx().mk_imm_ptr(substs[0].expect_ty()); - let unique_place = self.tcx().mk_place_field(self.place, Field::new(0), unique_ty); - let nonnull_place = self.tcx().mk_place_field(unique_place, Field::new(0), nonnull_ty); - let ptr_place = self.tcx().mk_place_field(nonnull_place, Field::new(0), ptr_ty); + let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::new(0), unique_ty); + let nonnull_place = self.tcx().mk_place_field(unique_place, FieldIdx::new(0), nonnull_ty); + let ptr_place = self.tcx().mk_place_field(nonnull_place, FieldIdx::new(0), ptr_ty); let interior = self.tcx().mk_place_deref(ptr_place); let interior_path = self.elaborator.deref_subpath(self.path); @@ -468,7 +468,7 @@ where let fields = self.move_paths_for_fields( self.place, self.path, - &adt.variant(VariantIdx::new(0)), + &adt.variant(FIRST_VARIANT), substs, ); self.drop_ladder(fields, succ, unwind) @@ -640,7 +640,7 @@ where args: vec![Operand::Move(Place::from(ref_place))], destination: unit_temp, target: Some(succ), - cleanup: unwind.into_option(), + unwind: unwind.into_action(), from_hir_call: true, fn_span: self.source_info.span, }, @@ -655,26 +655,20 @@ where /// /// ```text /// loop-block: - /// can_go = cur == length_or_end + /// can_go = cur == len /// if can_go then succ else drop-block /// drop-block: - /// if ptr_based { - /// ptr = cur - /// cur = cur.offset(1) - /// } else { - /// ptr = &raw mut P[cur] - /// cur = cur + 1 - /// } + /// ptr = &raw mut P[cur] + /// cur = cur + 1 /// drop(ptr) /// ``` fn drop_loop( &mut self, succ: BasicBlock, cur: Local, - length_or_end: Place<'tcx>, + len: Local, ety: Ty<'tcx>, unwind: Unwind, - ptr_based: bool, ) -> BasicBlock { let copy = |place: Place<'tcx>| Operand::Copy(place); let move_ = |place: Place<'tcx>| Operand::Move(place); @@ -683,22 +677,19 @@ where let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mut }); let ptr = Place::from(self.new_temp(ptr_ty)); let can_go = Place::from(self.new_temp(tcx.types.bool)); - let one = self.constant_usize(1); - let (ptr_next, cur_next) = if ptr_based { - ( - Rvalue::Use(copy(cur.into())), - Rvalue::BinaryOp(BinOp::Offset, Box::new((move_(cur.into()), one))), - ) - } else { - ( - Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)), - Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))), - ) - }; let drop_block = BasicBlockData { - statements: vec![self.assign(ptr, ptr_next), self.assign(Place::from(cur), cur_next)], + statements: vec![ + self.assign( + ptr, + Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)), + ), + self.assign( + cur.into(), + Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))), + ), + ], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { source_info: self.source_info, @@ -711,10 +702,7 @@ where let loop_block = BasicBlockData { statements: vec![self.assign( can_go, - Rvalue::BinaryOp( - BinOp::Eq, - Box::new((copy(Place::from(cur)), copy(length_or_end))), - ), + Rvalue::BinaryOp(BinOp::Eq, Box::new((copy(Place::from(cur)), copy(len.into())))), )], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { @@ -729,7 +717,7 @@ where TerminatorKind::Drop { place: tcx.mk_place_deref(ptr), target: loop_block, - unwind: unwind.into_option(), + unwind: unwind.into_action(), }, ); @@ -738,118 +726,97 @@ where fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> BasicBlock { debug!("open_drop_for_array({:?}, {:?})", ety, opt_size); - - // if size_of::<ety>() == 0 { - // index_based_loop - // } else { - // ptr_based_loop - // } - 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; } } - let move_ = |place: Place<'tcx>| Operand::Move(place); - let elem_size = Place::from(self.new_temp(tcx.types.usize)); - let len = Place::from(self.new_temp(tcx.types.usize)); - - let base_block = BasicBlockData { - statements: vec![ - self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), - self.assign(len, Rvalue::Len(self.place)), - ], - is_cleanup: self.unwind.is_cleanup(), - terminator: Some(Terminator { - source_info: self.source_info, - kind: TerminatorKind::SwitchInt { - discr: move_(elem_size), - targets: SwitchTargets::static_if( - 0, - self.drop_loop_pair(ety, false, len), - self.drop_loop_pair(ety, true, len), - ), - }, - }), - }; - self.elaborator.patch().new_block(base_block) + self.drop_loop_pair(ety) } /// Creates a pair of drop-loops of `place`, which drops its contents, even - /// in the case of 1 panic. If `ptr_based`, creates a pointer loop, - /// otherwise create an index loop. - fn drop_loop_pair( - &mut self, - ety: Ty<'tcx>, - ptr_based: bool, - length: Place<'tcx>, - ) -> BasicBlock { - debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based); + /// in the case of 1 panic. + fn drop_loop_pair(&mut self, ety: Ty<'tcx>) -> BasicBlock { + debug!("drop_loop_pair({:?})", ety); let tcx = self.tcx(); - let iter_ty = if ptr_based { tcx.mk_mut_ptr(ety) } else { tcx.types.usize }; + let len = self.new_temp(tcx.types.usize); + let cur = self.new_temp(tcx.types.usize); - let cur = self.new_temp(iter_ty); - let length_or_end = if ptr_based { Place::from(self.new_temp(iter_ty)) } else { length }; + let unwind = + self.unwind.map(|unwind| self.drop_loop(unwind, cur, len, ety, Unwind::InCleanup)); - let unwind = self.unwind.map(|unwind| { - self.drop_loop(unwind, cur, length_or_end, ety, Unwind::InCleanup, ptr_based) - }); + let loop_block = self.drop_loop(self.succ, cur, len, ety, unwind); - let loop_block = self.drop_loop(self.succ, cur, length_or_end, ety, unwind, ptr_based); - - let cur = Place::from(cur); - let drop_block_stmts = if ptr_based { - let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); - let tmp = Place::from(self.new_temp(tmp_ty)); - // tmp = &raw mut P; - // cur = tmp as *mut T; - // end = Offset(cur, len); - let mir_cast_kind = ty::cast::mir_cast_kind(iter_ty, tmp_ty); - vec![ - self.assign(tmp, Rvalue::AddressOf(Mutability::Mut, self.place)), - self.assign(cur, Rvalue::Cast(mir_cast_kind, Operand::Move(tmp), iter_ty)), - self.assign( - length_or_end, - Rvalue::BinaryOp( - BinOp::Offset, - Box::new((Operand::Copy(cur), Operand::Move(length))), - ), - ), - ] - } else { - // cur = 0 (length already pushed) - let zero = self.constant_usize(0); - vec![self.assign(cur, Rvalue::Use(zero))] - }; - let drop_block = self.elaborator.patch().new_block(BasicBlockData { - statements: drop_block_stmts, + let zero = self.constant_usize(0); + let block = BasicBlockData { + statements: vec![ + self.assign(len.into(), Rvalue::Len(self.place)), + self.assign(cur.into(), Rvalue::Use(zero)), + ], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { source_info: self.source_info, kind: TerminatorKind::Goto { target: loop_block }, }), - }); + }; + let drop_block = self.elaborator.patch().new_block(block); // FIXME(#34708): handle partially-dropped array/slice elements. let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind); self.drop_flag_test_block(reset_block, self.succ, unwind) @@ -893,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), } @@ -963,12 +930,12 @@ where let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); let free_func = tcx.require_lang_item(LangItem::BoxFree, Some(self.source_info.span)); let args = adt - .variant(VariantIdx::new(0)) + .variant(FIRST_VARIANT) .fields .iter() .enumerate() .map(|(i, f)| { - let field = Field::new(i); + let field = FieldIdx::new(i); let field_ty = f.ty(tcx, substs); Operand::Move(tcx.mk_place_field(self.place, field, field_ty)) }) @@ -979,7 +946,11 @@ where args, destination: unit_temp, target: Some(target), - cleanup: None, + unwind: if unwind.is_cleanup() { + UnwindAction::Terminate + } else { + UnwindAction::Continue + }, from_hir_call: false, fn_span: self.source_info.span, }; // FIXME(#43234) @@ -992,7 +963,7 @@ where fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock { let block = - TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_option() }; + TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_action() }; self.new_block(unwind, block) } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 2ae3ae02f..c8fe1af66 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets}; +use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets, UnwindAction}; use rustc_middle::ty::TyCtxt; use std::ops::RangeInclusive; @@ -474,15 +474,14 @@ impl Direction for Forward { { use mir::TerminatorKind::*; match bb_data.terminator().kind { - Return | Resume | Abort | GeneratorDrop | Unreachable => {} + Return | Resume | Terminate | GeneratorDrop | Unreachable => {} Goto { target } => propagate(target, exit_state), - Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ } + Assert { target, unwind, expected: _, msg: _, cond: _ } | Drop { target, unwind, place: _ } - | DropAndReplace { target, unwind, value: _, place: _ } | FalseUnwind { real_target: target, unwind } => { - if let Some(unwind) = unwind { + if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } @@ -504,7 +503,7 @@ impl Direction for Forward { } Call { - cleanup, + unwind, destination, target, func: _, @@ -512,7 +511,7 @@ impl Direction for Forward { from_hir_call: _, fn_span: _, } => { - if let Some(unwind) = cleanup { + if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } @@ -534,9 +533,9 @@ impl Direction for Forward { options: _, line_spans: _, destination, - cleanup, + unwind, } => { - if let Some(unwind) = cleanup { + if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 91c3bf0ad..2abdee064 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -15,6 +15,7 @@ use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::{self, traversal, BasicBlock}; use rustc_middle::mir::{create_dump_file, dump_enabled}; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; @@ -285,7 +286,7 @@ where if tcx.sess.opts.unstable_opts.graphviz_dark_mode { render_opts.push(dot::RenderOption::DarkTheme); } - dot::render_opts(&graphviz, &mut buf, &render_opts)?; + with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)?); file.write_all(&buf)?; diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 96c42894b..707729f8f 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -6,6 +6,7 @@ use std::{io, ops, str}; use regex::Regex; use rustc_graphviz as dot; +use rustc_index::bit_set::BitSet; use rustc_middle::mir::graphviz_safe_def_name; use rustc_middle::mir::{self, BasicBlock, Body, Location}; @@ -34,6 +35,7 @@ where body: &'a Body<'tcx>, results: &'a Results<'tcx, A>, style: OutputStyle, + reachable: BitSet<BasicBlock>, } impl<'a, 'tcx, A> Formatter<'a, 'tcx, A> @@ -41,7 +43,8 @@ where A: Analysis<'tcx>, { pub fn new(body: &'a Body<'tcx>, results: &'a Results<'tcx, A>, style: OutputStyle) -> Self { - Formatter { body, results, style } + let reachable = mir::traversal::reachable_as_bitset(body); + Formatter { body, results, style, reachable } } } @@ -108,7 +111,12 @@ where type Edge = CfgEdge; fn nodes(&self) -> dot::Nodes<'_, Self::Node> { - self.body.basic_blocks.indices().collect::<Vec<_>>().into() + self.body + .basic_blocks + .indices() + .filter(|&idx| self.reachable.contains(idx)) + .collect::<Vec<_>>() + .into() } fn edges(&self) -> dot::Edges<'_, Self::Edge> { @@ -386,8 +394,8 @@ where ) -> io::Result<()> { let diffs = StateDiffCollector::run(body, block, self.results.results(), self.style); - let mut befores = diffs.before.map(|v| v.into_iter()); - let mut afters = diffs.after.into_iter(); + let mut diffs_before = diffs.before.map(|v| v.into_iter()); + let mut diffs_after = diffs.after.into_iter(); let next_in_dataflow_order = |it: &mut std::vec::IntoIter<_>| { if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() } @@ -397,8 +405,8 @@ where let statement_str = format!("{statement:?}"); let index_str = format!("{i}"); - let after = next_in_dataflow_order(&mut afters); - let before = befores.as_mut().map(next_in_dataflow_order); + let after = next_in_dataflow_order(&mut diffs_after); + let before = diffs_before.as_mut().map(next_in_dataflow_order); self.write_row(w, &index_str, &statement_str, |_this, w, fmt| { if let Some(before) = before { @@ -409,11 +417,11 @@ where })?; } - let after = next_in_dataflow_order(&mut afters); - let before = befores.as_mut().map(next_in_dataflow_order); + let after = next_in_dataflow_order(&mut diffs_after); + let before = diffs_before.as_mut().map(next_in_dataflow_order); - assert!(afters.is_empty()); - assert!(befores.as_ref().map_or(true, ExactSizeIterator::is_empty)); + assert!(diffs_after.is_empty()); + assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty)); let terminator = body[block].terminator(); let mut terminator_str = String::new(); diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 17102454a..60679b17d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -39,7 +39,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { args: vec![], destination: dummy_place.clone(), target: Some(mir::START_BLOCK), - cleanup: None, + unwind: mir::UnwindAction::Continue, from_hir_call: false, fn_span: DUMMY_SP, }, @@ -53,7 +53,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { args: vec![], destination: dummy_place.clone(), target: Some(mir::START_BLOCK), - cleanup: None, + unwind: mir::UnwindAction::Continue, from_hir_call: false, fn_span: DUMMY_SP, }, diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 6f4e7fd46..92d30f254 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -111,8 +111,7 @@ where self.super_terminator(terminator, location); match terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } => { // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut // self` as a parameter. In the general case, a drop impl could launder that // reference into the surrounding environment through a raw pointer, thus creating @@ -126,7 +125,7 @@ where } } - TerminatorKind::Abort + TerminatorKind::Terminate | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 633a5674f..1309ea525 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -198,8 +198,7 @@ impl DefUse { | NonMutatingUseContext::Inspect | NonMutatingUseContext::Move | NonMutatingUseContext::ShallowBorrow - | NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::UniqueBorrow, + | NonMutatingUseContext::SharedBorrow, ) => Some(DefUse::Use), PlaceContext::MutatingUse(MutatingUseContext::Projection) @@ -263,6 +262,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { | StatementKind::StorageDead(_) | StatementKind::Retag(..) | StatementKind::AscribeUserType(..) + | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index fcf0ce9d8..4a5d9d520 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -139,6 +139,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. StatementKind::AscribeUserType(..) + | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::FakeRead(..) | StatementKind::ConstEvalCounter @@ -199,10 +200,9 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. - TerminatorKind::Abort + TerminatorKind::Terminate | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop @@ -237,10 +237,9 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Yield { .. } - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b1e03faff..43caa2ea9 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -3,7 +3,6 @@ #![feature(exact_size_is_empty)] #![feature(let_chains)] #![feature(min_specialization)] -#![feature(once_cell)] #![feature(stmt_expr_attributes)] #![feature(trusted_step)] #![recursion_limit = "256"] @@ -46,7 +45,7 @@ pub mod storage; pub mod un_derefer; pub mod value_analysis; -fluent_messages! { "../locales/en-US.ftl" } +fluent_messages! { "../messages.ftl" } pub(crate) mod indexes { pub(crate) use super::move_paths::MovePathIndex; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 4a163028f..64ed7a29f 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -329,6 +329,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } StatementKind::Retag { .. } | StatementKind::AscribeUserType(..) + | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter @@ -374,7 +375,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // need recording. | TerminatorKind::Return | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } => {} @@ -392,17 +393,12 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.create_move_path(place); self.gather_init(place.as_ref(), InitKind::Deep); } - TerminatorKind::DropAndReplace { place, ref value, .. } => { - self.create_move_path(place); - self.gather_operand(value); - self.gather_init(place.as_ref(), InitKind::Deep); - } TerminatorKind::Call { ref func, ref args, destination, target, - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _, } => { @@ -421,7 +417,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { options: _, line_spans: _, destination: _, - cleanup: _, + unwind: _, } => { for op in operands { match *op { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 5f22a418d..257a42cdd 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -1,6 +1,6 @@ use crate::move_paths::builder::MoveDat; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::IndexVec; +use rustc_index::vec::{IndexSlice, IndexVec}; use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_span::Span; @@ -64,7 +64,7 @@ impl<'tcx> MovePath<'tcx> { /// Returns an iterator over the parents of `self`. pub fn parents<'a>( &self, - move_paths: &'a IndexVec<MovePathIndex, MovePath<'tcx>>, + move_paths: &'a IndexSlice<MovePathIndex, MovePath<'tcx>>, ) -> impl 'a + Iterator<Item = (MovePathIndex, &'a MovePath<'tcx>)> { let first = self.parent.map(|mpi| (mpi, &move_paths[mpi])); MovePathLinearIter { @@ -78,7 +78,7 @@ impl<'tcx> MovePath<'tcx> { /// Returns an iterator over the immediate children of `self`. pub fn children<'a>( &self, - move_paths: &'a IndexVec<MovePathIndex, MovePath<'tcx>>, + move_paths: &'a IndexSlice<MovePathIndex, MovePath<'tcx>>, ) -> impl 'a + Iterator<Item = (MovePathIndex, &'a MovePath<'tcx>)> { let first = self.first_child.map(|mpi| (mpi, &move_paths[mpi])); MovePathLinearIter { @@ -95,7 +95,7 @@ impl<'tcx> MovePath<'tcx> { /// `f` will **not** be called on `self`. pub fn find_descendant( &self, - move_paths: &IndexVec<MovePathIndex, MovePath<'_>>, + move_paths: &IndexSlice<MovePathIndex, MovePath<'_>>, f: impl Fn(MovePathIndex) -> bool, ) -> Option<MovePathIndex> { let mut todo = if let Some(child) = self.first_child { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 401db890a..98bebc9b1 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -36,11 +36,11 @@ use std::fmt::{Debug, Formatter}; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_index::vec::{IndexSlice, IndexVec}; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use crate::lattice::{HasBottom, HasTop}; use crate::{ @@ -86,6 +86,7 @@ pub trait ValueAnalysis<'tcx> { StatementKind::ConstEvalCounter | StatementKind::Nop | StatementKind::FakeRead(..) + | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::AscribeUserType(..) => (), } @@ -230,14 +231,14 @@ pub trait ValueAnalysis<'tcx> { TerminatorKind::Drop { place, .. } => { state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } - TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { + TerminatorKind::Yield { .. } => { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); } TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Assert { .. } @@ -690,7 +691,7 @@ impl Map { } // Recurse with all fields of this place. - iter_fields(ty, tcx, |variant, field, ty| { + iter_fields(ty, tcx, ty::ParamEnv::reveal_all(), |variant, field, ty| { if let Some(variant) = variant { projection.push(PlaceElem::Downcast(None, variant)); let _ = self.make_place(local, projection); @@ -918,7 +919,7 @@ impl<V: HasTop> ValueOrPlace<V> { /// Although only field projections are currently allowed, this could change in the future. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TrackElem { - Field(Field), + Field(FieldIdx), Variant(VariantIdx), Discriminant, } @@ -939,7 +940,8 @@ impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem { pub fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - mut f: impl FnMut(Option<VariantIdx>, Field, Ty<'tcx>), + param_env: ty::ParamEnv<'tcx>, + mut f: impl FnMut(Option<VariantIdx>, FieldIdx, Ty<'tcx>), ) { match ty.kind() { ty::Tuple(list) => { @@ -956,14 +958,14 @@ pub fn iter_fields<'tcx>( for (f_index, f_def) in v_def.fields.iter().enumerate() { let field_ty = f_def.ty(tcx, substs); let field_ty = tcx - .try_normalize_erasing_regions(ty::ParamEnv::reveal_all(), field_ty) - .unwrap_or(field_ty); + .try_normalize_erasing_regions(param_env, field_ty) + .unwrap_or_else(|_| tcx.erase_regions(field_ty)); f(variant, f_index.into(), field_ty); } } } ty::Closure(_, substs) => { - iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, f); + iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, param_env, f); } _ => (), } @@ -1026,8 +1028,8 @@ where fn debug_with_context_rec<V: Debug + Eq>( place: PlaceIndex, place_str: &str, - new: &IndexVec<ValueIndex, V>, - old: Option<&IndexVec<ValueIndex, V>>, + new: &IndexSlice<ValueIndex, V>, + old: Option<&IndexSlice<ValueIndex, V>>, map: &Map, f: &mut Formatter<'_>, ) -> std::fmt::Result { @@ -1067,8 +1069,8 @@ fn debug_with_context_rec<V: Debug + Eq>( } fn debug_with_context<V: Debug + Eq>( - new: &IndexVec<ValueIndex, V>, - old: Option<&IndexVec<ValueIndex, V>>, + new: &IndexSlice<ValueIndex, V>, + old: Option<&IndexSlice<ValueIndex, V>>, map: &Map, f: &mut Formatter<'_>, ) -> std::fmt::Result { |