diff options
| author | Laurențiu Nicola <lnicola@users.noreply.github.com> | 2025-02-24 08:45:06 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-24 08:45:06 +0000 |
| commit | 6d9b9c1363e00e02ee72a08ba4ab3dd9d28ad1a1 (patch) | |
| tree | be062bef485315bf71029db86a4e67a57e7be633 /compiler/rustc_mir_transform/src | |
| parent | 286595e21ef26c7d243b7715033f2d0b72882a83 (diff) | |
| parent | a2bd5a5ed388c71b253c1ad5cdd35c570ea0418e (diff) | |
| download | rust-6d9b9c1363e00e02ee72a08ba4ab3dd9d28ad1a1.tar.gz rust-6d9b9c1363e00e02ee72a08ba4ab3dd9d28ad1a1.zip | |
Merge pull request #19212 from lnicola/sync-from-rust
minor: sync from downstream
Diffstat (limited to 'compiler/rustc_mir_transform/src')
27 files changed, 204 insertions, 200 deletions
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 3affe4abbfa..ceea72c6755 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -79,7 +79,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> { let lint_root = self.body.source_scopes[source_info.scope] .local_data .as_ref() - .assert_crate_local() + .unwrap_crate_local() .lint_root; Some((lint_root, source_info.span, self.tcx.def_span(const_item))) diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs index 497f4a660ea..83c3cda5a50 100644 --- a/compiler/rustc_mir_transform/src/check_inline.rs +++ b/compiler/rustc_mir_transform/src/check_inline.rs @@ -16,7 +16,7 @@ pub(super) struct CheckForceInline; impl<'tcx> MirLint<'tcx> for CheckForceInline { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id(); - if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() { + if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() { return; } let InlineAttr::Force { attr_span, .. } = tcx.codegen_fn_attrs(def_id).inline else { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index afc49c5cc54..04d96f11707 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -393,12 +393,13 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { // Remove StorageLive and StorageDead statements for remapped locals - data.retain_statements(|s| match s.kind { - StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => { - !self.remap.contains(l) + for s in &mut data.statements { + if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = s.kind + && self.remap.contains(l) + { + s.make_nop(); } - _ => true, - }); + } let ret_val = match data.terminator().kind { TerminatorKind::Return => { @@ -944,7 +945,7 @@ fn compute_layout<'tcx>( let decl = &body.local_decls[local]; debug!(?decl); - // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared + // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared // the information. This is alright, since `ignore_for_traits` is only relevant when // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer // default. diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 6d84248ddfb..09384defea8 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -2,7 +2,6 @@ use std::cmp::Ordering; use std::ops::{Index, IndexMut}; use std::{mem, slice}; -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::graph::{self, DirectedGraph, StartNode}; @@ -218,7 +217,7 @@ impl CoverageGraph { pub(crate) fn reloop_predecessors( &self, to_bcb: BasicCoverageBlock, - ) -> impl Iterator<Item = BasicCoverageBlock> + Captures<'_> { + ) -> impl Iterator<Item = BasicCoverageBlock> { self.predecessors[to_bcb].iter().copied().filter(move |&pred| self.dominates(to_bcb, pred)) } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 264995efe8f..1ccae0fd7fe 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -346,35 +346,37 @@ fn extract_hole_spans_from_hir<'tcx>( body_span: Span, // Usually `hir_body.value.span`, but not always hir_body: &hir::Body<'tcx>, ) -> Vec<Span> { - struct HolesVisitor<'hir, F> { - tcx: TyCtxt<'hir>, - visit_hole_span: F, + struct HolesVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + body_span: Span, + hole_spans: Vec<Span>, } - impl<'hir, F: FnMut(Span)> Visitor<'hir> for HolesVisitor<'hir, F> { - /// - We need `NestedFilter::INTRA = true` so that `visit_item` will be called. - /// - Bodies of nested items don't actually get visited, because of the - /// `visit_item` override. - /// - For nested bodies that are not part of an item, we do want to visit any - /// items contained within them. - type NestedFilter = nested_filter::All; + impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> { + /// We have special handling for nested items, but we still want to + /// traverse into nested bodies of things that are not considered items, + /// such as "anon consts" (e.g. array lengths). + type NestedFilter = nested_filter::OnlyBodies; - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { self.tcx } - fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { - (self.visit_hole_span)(item.span); + /// We override `visit_nested_item` instead of `visit_item` because we + /// only need the item's span, not the item itself. + fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result { + let span = self.tcx.def_span(id.owner_id.def_id); + self.visit_hole_span(span); // Having visited this item, we don't care about its children, // so don't call `walk_item`. } // We override `visit_expr` instead of the more specific expression // visitors, so that we have direct access to the expression span. - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { match expr.kind { hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) => { - (self.visit_hole_span)(expr.span); + self.visit_hole_span(expr.span); // Having visited this expression, we don't care about its // children, so don't call `walk_expr`. } @@ -384,18 +386,17 @@ fn extract_hole_spans_from_hir<'tcx>( } } } - - let mut hole_spans = vec![]; - let mut visitor = HolesVisitor { - tcx, - visit_hole_span: |hole_span| { + impl HolesVisitor<'_> { + fn visit_hole_span(&mut self, hole_span: Span) { // Discard any holes that aren't directly visible within the body span. - if body_span.contains(hole_span) && body_span.eq_ctxt(hole_span) { - hole_spans.push(hole_span); + if self.body_span.contains(hole_span) && self.body_span.eq_ctxt(hole_span) { + self.hole_spans.push(hole_span); } - }, - }; + } + } + + let mut visitor = HolesVisitor { tcx, body_span, hole_spans: vec![] }; visitor.visit_body(hir_body); - hole_spans + visitor.hole_spans } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index ef86358b205..58461be01f1 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,4 +1,3 @@ -use rustc_data_structures::captures::Captures; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::{BasicCoverageBlock, CoverageIdsInfo, CoverageKind, MappingKind}; @@ -153,7 +152,7 @@ fn coverage_ids_info<'tcx>( fn all_coverage_in_mir_body<'a, 'tcx>( body: &'a Body<'tcx>, -) -> impl Iterator<Item = &'a CoverageKind> + Captures<'tcx> { +) -> impl Iterator<Item = &'a CoverageKind> { body.basic_blocks.iter().flat_map(|bb_data| &bb_data.statements).filter_map(|statement| { match statement.kind { StatementKind::Coverage(ref kind) if !is_inlined(body, statement) => Some(kind), diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 314a86ea52f..b9ed6984ddb 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,6 +1,5 @@ use std::collections::VecDeque; -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; @@ -182,7 +181,7 @@ fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Ve fn drain_front_while<'a, T>( queue: &'a mut VecDeque<T>, mut pred_fn: impl FnMut(&T) -> bool, -) -> impl Iterator<Item = T> + Captures<'a> { +) -> impl Iterator<Item = T> { std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None }) } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 2de55e38052..0d8cf524661 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -185,7 +185,7 @@ where place.ty(self.elaborator.body(), self.tcx()).ty } else { // We don't have a slice with all the locals, since some are in the patch. - tcx::PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local)) + PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local)) .multi_projection_ty(self.elaborator.tcx(), place.projection) .ty } @@ -266,8 +266,21 @@ where let tcx = self.tcx(); assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis); - let field_ty = - tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)); + // The type error for normalization may have been in dropck: see + // `compute_drop_data` in rustc_borrowck, in which case we wouldn't have + // deleted the MIR body and could have an error here as well. + let field_ty = match tcx + .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)) + { + Ok(t) => t, + Err(_) => Ty::new_error( + self.tcx(), + self.elaborator + .body() + .tainted_by_errors + .expect("Error in drop elaboration not found by dropck."), + ), + }; (tcx.mk_place_field(base_place, field, field_ty), subpath) }) diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index ab6aafab446..530c72ca549 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -417,7 +417,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { .. } = data.terminator().kind { - assert!(!self.patch.is_patched(bb)); + assert!(!self.patch.is_term_patched(bb)); let loc = Location { block: tgt, statement_index: 0 }; let path = self.move_data().rev_lookup.find(destination.as_ref()); @@ -462,7 +462,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { // a Goto; see `MirPatch::new`). } _ => { - assert!(!self.patch.is_patched(bb)); + assert!(!self.patch.is_term_patched(bb)); } } } @@ -486,7 +486,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { .. } = data.terminator().kind { - assert!(!self.patch.is_patched(bb)); + assert!(!self.patch.is_term_patched(bb)); let loc = Location { block: bb, statement_index: data.statements.len() }; let path = self.move_data().rev_lookup.find(destination.as_ref()); diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 9a6a153c7ba..7b3553e7afd 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -85,7 +85,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let lint_root = body.source_scopes[terminator.source_info.scope] .local_data .as_ref() - .assert_crate_local() + .unwrap_crate_local() .lint_root; let span = terminator.source_info.span; @@ -113,7 +113,7 @@ fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option<PanicStrate return Some(PanicStrategy::Abort); } - for def_id in tcx.hir().body_owners() { + for def_id in tcx.hir_body_owners() { if tcx.has_ffi_unwind_calls(def_id) { // Given that this crate is compiled in `-C panic=unwind`, the `AbortUnwindingCalls` // MIR pass will not be run on FFI-unwind call sites, therefore a foreign exception diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 73e47bb79f0..38b5ccdb32e 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -154,7 +154,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let lint_root = self.body.source_scopes[source_info.scope] .local_data .as_ref() - .assert_crate_local() + .unwrap_crate_local() .lint_root; // FIXME: use existing printing routines to print the function signature let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 77a3854ebde..2f8a3050199 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1558,8 +1558,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return true; }; + if layout.uninhabited { + return true; + } + match layout.backend_repr { - BackendRepr::Uninhabited => true, BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx), BackendRepr::ScalarPair(a, b) => { !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 1f8392b2118..5981b5031c6 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -463,7 +463,7 @@ fn inline<'tcx, T: Inliner<'tcx>>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> b let def_id = body.source.def_id(); // Only do inlining into fn bodies. - if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() { + if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() { return false; } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 3dc4edaaa5a..da346dfc48c 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -36,7 +36,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { typing_env: body.typing_env(tcx), }; let preserve_ub_checks = - attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); + attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { match statement.kind { diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 17084eca6e3..0a72a9d669f 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -172,11 +172,11 @@ impl HasBottom for ConditionSet<'_> { } impl<'a> ConditionSet<'a> { - fn iter(self) -> impl Iterator<Item = Condition> + 'a { + fn iter(self) -> impl Iterator<Item = Condition> { self.0.iter().copied() } - fn iter_matches(self, value: ScalarInt) -> impl Iterator<Item = Condition> + 'a { + fn iter_matches(self, value: ScalarInt) -> impl Iterator<Item = Condition> { self.iter().filter(move |c| c.matches(value)) } @@ -467,7 +467,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { state.insert_place_idx(rhs, lhs, &self.map); } // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. - Rvalue::Aggregate(box ref kind, ref operands) => { + Rvalue::Aggregate(box kind, operands) => { let agg_ty = lhs_place.ty(self.body, self.tcx).ty; let lhs = match kind { // Do not support unions. diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 59de6ca84a7..f8db8de4e82 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -509,7 +509,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // other overflow checks. AssertKind::Overflow(*bin_op, eval_to_int(op1), eval_to_int(op2)) } - AssertKind::BoundsCheck { ref len, ref index } => { + AssertKind::BoundsCheck { len, index } => { let len = eval_to_int(len); let index = eval_to_int(index); AssertKind::BoundsCheck { len, index } @@ -782,10 +782,10 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { self.super_terminator(terminator, location); match &terminator.kind { - TerminatorKind::Assert { expected, ref msg, ref cond, .. } => { + TerminatorKind::Assert { expected, msg, cond, .. } => { self.check_assertion(*expected, msg, cond, location); } - TerminatorKind::SwitchInt { ref discr, ref targets } => { + TerminatorKind::SwitchInt { discr, targets } => { if let Some(ref value) = self.eval_operand(discr) && let Some(value_const) = self.use_ecx(|this| this.ecx.read_scalar(value)) && let Some(constant) = value_const.to_bits(value_const.size()).discard_err() diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 1e546bfbeb3..47cb478fe33 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -6,6 +6,8 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::Session; +use crate::patch::MirPatch; + /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large /// enough discrepancy between them. /// @@ -41,31 +43,34 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { let mut alloc_cache = FxHashMap::default(); let typing_env = body.typing_env(tcx); - let blocks = body.basic_blocks.as_mut(); - let local_decls = &mut body.local_decls; + let mut patch = MirPatch::new(body); - for bb in blocks { - bb.expand_statements(|st| { + for (block, data) in body.basic_blocks.as_mut().iter_enumerated_mut() { + for (statement_index, st) in data.statements.iter_mut().enumerate() { let StatementKind::Assign(box ( lhs, Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), )) = &st.kind else { - return None; + continue; }; - let ty = lhs.ty(local_decls, tcx).ty; + let location = Location { block, statement_index }; - let (adt_def, num_variants, alloc_id) = - self.candidate(tcx, typing_env, ty, &mut alloc_cache)?; + let ty = lhs.ty(&body.local_decls, tcx).ty; - let source_info = st.source_info; - let span = source_info.span; + let Some((adt_def, num_variants, alloc_id)) = + self.candidate(tcx, typing_env, ty, &mut alloc_cache) + else { + continue; + }; + + let span = st.source_info.span; let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); - let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); - let store_live = - Statement { source_info, kind: StatementKind::StorageLive(size_array_local) }; + let size_array_local = patch.new_temp(tmp_ty, span); + + let store_live = StatementKind::StorageLive(size_array_local); let place = Place::from(size_array_local); let constant_vals = ConstOperand { @@ -77,108 +82,63 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { ), }; let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); - let const_assign = - Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) }; - - let discr_place = Place::from( - local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), - ); - let store_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_place, - Rvalue::Discriminant(*rhs), - ))), - }; - - let discr_cast_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - let cast_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_cast_place, - Rvalue::Cast( - CastKind::IntToInt, - Operand::Copy(discr_place), - tcx.types.usize, - ), - ))), - }; - - let size_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - let store_size = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - size_place, - Rvalue::Use(Operand::Copy(Place { - local: size_array_local, - projection: tcx - .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), - })), - ))), - }; - - let dst = - Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span))); - let dst_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst, - Rvalue::RawPtr(RawPtrKind::Mut, *lhs), - ))), - }; + let const_assign = StatementKind::Assign(Box::new((place, rval))); + + let discr_place = + Place::from(patch.new_temp(adt_def.repr().discr_type().to_ty(tcx), span)); + let store_discr = + StatementKind::Assign(Box::new((discr_place, Rvalue::Discriminant(*rhs)))); + + let discr_cast_place = Place::from(patch.new_temp(tcx.types.usize, span)); + let cast_discr = StatementKind::Assign(Box::new(( + discr_cast_place, + Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr_place), tcx.types.usize), + ))); + + let size_place = Place::from(patch.new_temp(tcx.types.usize, span)); + let store_size = StatementKind::Assign(Box::new(( + size_place, + Rvalue::Use(Operand::Copy(Place { + local: size_array_local, + projection: tcx.mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), + })), + ))); + + let dst = Place::from(patch.new_temp(Ty::new_mut_ptr(tcx, ty), span)); + let dst_ptr = + StatementKind::Assign(Box::new((dst, Rvalue::RawPtr(RawPtrKind::Mut, *lhs)))); let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); - let dst_cast_place = - Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); - let dst_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), - ))), - }; + let dst_cast_place = Place::from(patch.new_temp(dst_cast_ty, span)); + let dst_cast = StatementKind::Assign(Box::new(( + dst_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), + ))); - let src = - Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span))); - let src_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src, - Rvalue::RawPtr(RawPtrKind::Const, *rhs), - ))), - }; + let src = Place::from(patch.new_temp(Ty::new_imm_ptr(tcx, ty), span)); + let src_ptr = + StatementKind::Assign(Box::new((src, Rvalue::RawPtr(RawPtrKind::Const, *rhs)))); let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); - let src_cast_place = - Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); - let src_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), - ))), - }; + let src_cast_place = Place::from(patch.new_temp(src_cast_ty, span)); + let src_cast = StatementKind::Assign(Box::new(( + src_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), + ))); - let deinit_old = - Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) }; - - let copy_bytes = Statement { - source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src: Operand::Copy(src_cast_place), - dst: Operand::Copy(dst_cast_place), - count: Operand::Copy(size_place), - }), - )), - }; + let deinit_old = StatementKind::Deinit(Box::new(dst)); + + let copy_bytes = StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + src: Operand::Copy(src_cast_place), + dst: Operand::Copy(dst_cast_place), + count: Operand::Copy(size_place), + }), + )); - let store_dead = - Statement { source_info, kind: StatementKind::StorageDead(size_array_local) }; + let store_dead = StatementKind::StorageDead(size_array_local); - let iter = [ + let stmts = [ store_live, const_assign, store_discr, @@ -191,14 +151,16 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { deinit_old, copy_bytes, store_dead, - ] - .into_iter(); + ]; + for stmt in stmts { + patch.add_statement(location, stmt); + } st.make_nop(); - - Some(iter) - }); + } } + + patch.apply(body); } fn is_required(&self) -> bool { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 46abdcb2a87..04c9375b831 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -314,11 +314,11 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// MIR associated with them. fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> { // All body-owners have MIR associated with them. - let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect(); + let mut set: FxIndexSet<_> = tcx.hir_body_owners().collect(); // Coroutine-closures (e.g. async closures) have an additional by-move MIR // body that isn't in the HIR. - for body_owner in tcx.hir().body_owners() { + for body_owner in tcx.hir_body_owners() { if let DefKind::Closure = tcx.def_kind(body_owner) && tcx.needs_coroutine_by_move_body_def_id(body_owner.to_def_id()) { @@ -470,7 +470,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { } let body = tcx.mir_drops_elaborated_and_const_checked(def); - let body = match tcx.hir().body_const_context(def) { + let body = match tcx.hir_body_const_context(def) { // consts and statics do not have `optimized_mir`, so we can steal the body instead of // cloning it. Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => body.steal(), @@ -729,7 +729,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { return shim::build_adt_ctor(tcx, did.to_def_id()); } - match tcx.hir().body_const_context(did) { + match tcx.hir_body_const_context(did) { // Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked` // which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it // computes and caches its result. diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 50d10883d2c..e3260e45bc5 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -186,7 +186,7 @@ fn true_significant_drop_ty<'tcx>( debug!(?name_str); match name_str[..] { // These are the types from Rust core ecosystem - ["sym" | "proc_macro2", ..] + ["syn" | "proc_macro2", ..] | ["core" | "std", "task", "LocalWaker" | "Waker"] | ["core" | "std", "task", "wake", "LocalWaker" | "Waker"] => Some(smallvec![]), // These are important types from Rust ecosystem diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index f5c57418467..9fd8d81d64a 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -51,7 +51,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { let ty = place.ty(self.body, self.tcx).ty; self.mentioned_items.push(Spanned { node: MentionedItem::Drop(ty), span: span() }); } - mir::TerminatorKind::InlineAsm { ref operands, .. } => { + mir::TerminatorKind::InlineAsm { operands, .. } => { for op in operands { match *op { mir::InlineAsmOperand::SymFn { ref value } => { diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index b4f6fa514a4..6a177faeac8 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -4,11 +4,12 @@ use rustc_middle::ty::Ty; use rustc_span::Span; use tracing::debug; -/// This struct represents a patch to MIR, which can add -/// new statements and basic blocks and patch over block -/// terminators. +/// This struct lets you "patch" a MIR body, i.e. modify it. You can queue up +/// various changes, such as the addition of new statements and basic blocks +/// and replacement of terminators, and then apply the queued changes all at +/// once with `apply`. This is useful for MIR transformation passes. pub(crate) struct MirPatch<'tcx> { - patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>, + term_patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>, new_blocks: Vec<BasicBlockData<'tcx>>, new_statements: Vec<(Location, StatementKind<'tcx>)>, new_locals: Vec<LocalDecl<'tcx>>, @@ -24,9 +25,10 @@ pub(crate) struct MirPatch<'tcx> { } impl<'tcx> MirPatch<'tcx> { + /// Creates a new, empty patch. pub(crate) fn new(body: &Body<'tcx>) -> Self { let mut result = MirPatch { - patch_map: IndexVec::from_elem(None, &body.basic_blocks), + term_patch_map: IndexVec::from_elem(None, &body.basic_blocks), new_blocks: vec![], new_statements: vec![], new_locals: vec![], @@ -141,10 +143,12 @@ impl<'tcx> MirPatch<'tcx> { bb } - pub(crate) fn is_patched(&self, bb: BasicBlock) -> bool { - self.patch_map[bb].is_some() + /// Has a replacement of this block's terminator been queued in this patch? + pub(crate) fn is_term_patched(&self, bb: BasicBlock) -> bool { + self.term_patch_map[bb].is_some() } + /// Queues the addition of a new temporary with additional local info. pub(crate) fn new_local_with_info( &mut self, ty: Ty<'tcx>, @@ -154,11 +158,12 @@ impl<'tcx> MirPatch<'tcx> { let index = self.next_local; self.next_local += 1; let mut new_decl = LocalDecl::new(ty, span); - **new_decl.local_info.as_mut().assert_crate_local() = local_info; + **new_decl.local_info.as_mut().unwrap_crate_local() = local_info; self.new_locals.push(new_decl); Local::new(index) } + /// Queues the addition of a new temporary. pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; @@ -174,29 +179,46 @@ impl<'tcx> MirPatch<'tcx> { self.new_locals[new_local_idx].ty } + /// Queues the addition of a new basic block. pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock { - let block = BasicBlock::new(self.patch_map.len()); + let block = BasicBlock::new(self.term_patch_map.len()); debug!("MirPatch: new_block: {:?}: {:?}", block, data); self.new_blocks.push(data); - self.patch_map.push(None); + self.term_patch_map.push(None); block } + /// Queues the replacement of a block's terminator. pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) { - assert!(self.patch_map[block].is_none()); + assert!(self.term_patch_map[block].is_none()); debug!("MirPatch: patch_terminator({:?}, {:?})", block, new); - self.patch_map[block] = Some(new); + self.term_patch_map[block] = Some(new); } + /// Queues the insertion of a statement at a given location. The statement + /// currently at that location, and all statements that follow, are shifted + /// down. If multiple statements are queued for addition at the same + /// location, the final statement order after calling `apply` will match + /// the queue insertion order. + /// + /// E.g. if we have `s0` at location `loc` and do these calls: + /// + /// p.add_statement(loc, s1); + /// p.add_statement(loc, s2); + /// p.apply(body); + /// + /// then the final order will be `s1, s2, s0`, with `s1` at `loc`. pub(crate) fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) { debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt); self.new_statements.push((loc, stmt)); } + /// Like `add_statement`, but specialized for assignments. pub(crate) fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) { self.add_statement(loc, StatementKind::Assign(Box::new((place, rv)))); } + /// Applies the queued changes. pub(crate) fn apply(self, body: &mut Body<'tcx>) { debug!( "MirPatch: {:?} new temps, starting from index {}: {:?}", @@ -209,14 +231,14 @@ impl<'tcx> MirPatch<'tcx> { self.new_blocks.len(), body.basic_blocks.len() ); - let bbs = if self.patch_map.is_empty() && self.new_blocks.is_empty() { + let bbs = if self.term_patch_map.is_empty() && self.new_blocks.is_empty() { body.basic_blocks.as_mut_preserves_cfg() } else { body.basic_blocks.as_mut() }; bbs.extend(self.new_blocks); body.local_decls.extend(self.new_locals); - for (src, patch) in self.patch_map.into_iter_enumerated() { + for (src, patch) in self.term_patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); bbs[src].terminator_mut().kind = patch; @@ -224,6 +246,9 @@ impl<'tcx> MirPatch<'tcx> { } let mut new_statements = self.new_statements; + + // This must be a stable sort to provide the ordering described in the + // comment for `add_statement`. new_statements.sort_by_key(|s| s.0); let mut delta = 0; diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 67070f03ded..84905f4a400 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -568,9 +568,9 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod } StatementKind::Assign(box (place, _)) => used_locals.is_used(place.local), - StatementKind::SetDiscriminant { ref place, .. } - | StatementKind::BackwardIncompatibleDropHint { ref place, reason: _ } - | StatementKind::Deinit(ref place) => used_locals.is_used(place.local), + StatementKind::SetDiscriminant { place, .. } + | StatementKind::BackwardIncompatibleDropHint { place, reason: _ } + | StatementKind::Deinit(place) => used_locals.is_used(place.local), StatementKind::Nop => false, _ => true, }; diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 12c3503879f..886f4d6e509 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -24,7 +24,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { // Simplify `assume` of a known value: either a NOP or unreachable. if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind && let NonDivergingIntrinsic::Assume(discr) = intrinsic - && let Operand::Constant(ref c) = discr + && let Operand::Constant(c) = discr && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env) { if constant { diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 21bc51ecca1..bd008230731 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -89,10 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { use Operand::*; match rhs { - Rvalue::BinaryOp(_, box (ref mut left @ Move(_), Constant(_))) => { + Rvalue::BinaryOp(_, box (left @ Move(_), Constant(_))) => { *left = Copy(opt.to_switch_on); } - Rvalue::BinaryOp(_, box (Constant(_), ref mut right @ Move(_))) => { + Rvalue::BinaryOp(_, box (Constant(_), right @ Move(_))) => { *right = Copy(opt.to_switch_on); } _ => (), diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index c5e951eb8b2..02caa92ad3f 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -48,9 +48,11 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { // We're only changing an operand, not the terminator kinds or successors let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); - let init_statement = - basic_blocks[init_loc.block].statements[init_loc.statement_index].replace_nop(); - let StatementKind::Assign(place_and_rvalue) = init_statement.kind else { + let init_statement_kind = std::mem::replace( + &mut basic_blocks[init_loc.block].statements[init_loc.statement_index].kind, + StatementKind::Nop, + ); + let StatementKind::Assign(place_and_rvalue) = init_statement_kind else { bug!("No longer an assign?"); }; let (place, rvalue) = *place_and_rvalue; diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 28de99f9193..7c6ccc89c4f 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -185,7 +185,7 @@ impl<'tcx> ReplacementMap<'tcx> { fn place_fragments( &self, place: Place<'tcx>, - ) -> Option<impl Iterator<Item = (FieldIdx, Ty<'tcx>, Local)> + '_> { + ) -> Option<impl Iterator<Item = (FieldIdx, Ty<'tcx>, Local)>> { let local = place.as_local()?; let fields = self.fragments[local].as_ref()?; Some(fields.iter_enumerated().filter_map(|(field, &opt_ty_local)| { diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 9f769077e77..3d512fb064e 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -138,7 +138,7 @@ impl SsaLocals { pub(super) fn assignments<'a, 'tcx>( &'a self, body: &'a Body<'tcx>, - ) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>, Location)> + 'a { + ) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>, Location)> { self.assignment_order.iter().filter_map(|&local| { if let Set1::One(DefLocation::Assignment(loc)) = self.assignments[local] { let stmt = body.stmt_at(loc).left()?; |
