about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-12-18 00:14:56 +0000
committerbors <bors@rust-lang.org>2024-12-18 00:14:56 +0000
commit52890e82153cd8716d97a96f47fb6ac99dec65be (patch)
tree5a23f57eb7b0a59a6647763b3f7ad847fe02ece9 /compiler
parent7e6bf003f396aeea510577b4e925d1d95c12ff53 (diff)
parent3b0df8c59f8811be5eb3b587c33ce75f0e788876 (diff)
downloadrust-52890e82153cd8716d97a96f47fb6ac99dec65be.tar.gz
rust-52890e82153cd8716d97a96f47fb6ac99dec65be.zip
Auto merge of #134439 - matthiaskrgr:rollup-grmmmx2, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #133265 (Add a range argument to vec.extract_if)
 - #133801 (Promote powerpc64le-unknown-linux-musl to tier 2 with host tools)
 - #134323 (coverage: Dismantle `map_data.rs` by moving its responsibilities elsewhere)
 - #134378 (An octuple of polonius fact generation cleanups)
 - #134408 (Regression test for RPIT inheriting lifetime from projection)
 - #134423 (bootstrap: use specific-purpose ui test path for `test_valid` self-test)
 - #134426 (Fix typo in uint_macros.rs)

Failed merges:

 - #133103 (Pass FnAbi to find_mir_or_eval_fn)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/nll.rs1
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/accesses.rs85
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs16
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs24
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/mod.rs117
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs123
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs121
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs84
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs150
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs80
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs19
-rw-r--r--compiler/rustc_errors/src/lib.rs8
-rw-r--r--compiler/rustc_lint/src/non_ascii_idents.rs4
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs6
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
21 files changed, 384 insertions, 479 deletions
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index d7ea8e1bcc2..2bd067d4161 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -124,6 +124,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         borrow_set,
         move_data,
         &universal_region_relations,
+        &constraints,
     );
 
     let mut regioncx = RegionInferenceContext::new(
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
new file mode 100644
index 00000000000..9c4aa8ea1ed
--- /dev/null
+++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
@@ -0,0 +1,85 @@
+use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::{Body, Local, Location, Place};
+use rustc_middle::ty::TyCtxt;
+use rustc_mir_dataflow::move_paths::{LookupResult, MoveData};
+use tracing::debug;
+
+use crate::def_use::{self, DefUse};
+use crate::facts::AllFacts;
+use crate::location::{LocationIndex, LocationTable};
+use crate::universal_regions::UniversalRegions;
+
+/// Emit polonius facts for variable defs, uses, drops, and path accesses.
+pub(crate) fn emit_access_facts<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    facts: &mut AllFacts,
+    body: &Body<'tcx>,
+    location_table: &LocationTable,
+    move_data: &MoveData<'tcx>,
+    universal_regions: &UniversalRegions<'tcx>,
+) {
+    let mut extractor = AccessFactsExtractor { facts, move_data, location_table };
+    extractor.visit_body(body);
+
+    for (local, local_decl) in body.local_decls.iter_enumerated() {
+        debug!("add use_of_var_derefs_origin facts - local={:?}, type={:?}", local, local_decl.ty);
+        tcx.for_each_free_region(&local_decl.ty, |region| {
+            let region_vid = universal_regions.to_region_vid(region);
+            facts.use_of_var_derefs_origin.push((local, region_vid.into()));
+        });
+    }
+}
+
+/// MIR visitor extracting point-wise facts about accesses.
+struct AccessFactsExtractor<'a, 'tcx> {
+    facts: &'a mut AllFacts,
+    move_data: &'a MoveData<'tcx>,
+    location_table: &'a LocationTable,
+}
+
+impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
+    fn location_to_index(&self, location: Location) -> LocationIndex {
+        self.location_table.mid_index(location)
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
+    fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
+        match def_use::categorize(context) {
+            Some(DefUse::Def) => {
+                debug!("AccessFactsExtractor - emit def");
+                self.facts.var_defined_at.push((local, self.location_to_index(location)));
+            }
+            Some(DefUse::Use) => {
+                debug!("AccessFactsExtractor - emit use");
+                self.facts.var_used_at.push((local, self.location_to_index(location)));
+            }
+            Some(DefUse::Drop) => {
+                debug!("AccessFactsExtractor - emit drop");
+                self.facts.var_dropped_at.push((local, self.location_to_index(location)));
+            }
+            _ => (),
+        }
+    }
+
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
+        self.super_place(place, context, location);
+
+        match context {
+            PlaceContext::NonMutatingUse(_)
+            | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
+                let path = match self.move_data.rev_lookup.find(place.as_ref()) {
+                    LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
+                    _ => {
+                        // There's no path access to emit.
+                        return;
+                    }
+                };
+                debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
+                self.facts.path_accessed_at_base.push((path, self.location_to_index(location)));
+            }
+
+            _ => {}
+        }
+    }
+}
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
index f646beeecf7..0d5b6f3a2c8 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
@@ -21,22 +21,22 @@ use crate::{
 /// Emit `loan_invalidated_at` facts.
 pub(super) fn emit_loan_invalidations<'tcx>(
     tcx: TyCtxt<'tcx>,
-    all_facts: &mut AllFacts,
-    location_table: &LocationTable,
+    facts: &mut AllFacts,
     body: &Body<'tcx>,
+    location_table: &LocationTable,
     borrow_set: &BorrowSet<'tcx>,
 ) {
     let dominators = body.basic_blocks.dominators();
     let mut visitor =
-        LoanInvalidationsGenerator { all_facts, borrow_set, tcx, location_table, body, dominators };
+        LoanInvalidationsGenerator { facts, borrow_set, tcx, location_table, body, dominators };
     visitor.visit_body(body);
 }
 
 struct LoanInvalidationsGenerator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    all_facts: &'a mut AllFacts,
-    location_table: &'a LocationTable,
+    facts: &'a mut AllFacts,
     body: &'a Body<'tcx>,
+    location_table: &'a LocationTable,
     dominators: &'a Dominators<BasicBlock>,
     borrow_set: &'a BorrowSet<'tcx>,
 }
@@ -151,7 +151,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
                 let resume = self.location_table.start_index(resume.start_location());
                 for (i, data) in borrow_set.iter_enumerated() {
                     if borrow_of_local_data(data.borrowed_place) {
-                        self.all_facts.loan_invalidated_at.push((resume, i));
+                        self.facts.loan_invalidated_at.push((resume, i));
                     }
                 }
 
@@ -165,7 +165,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
                 let start = self.location_table.start_index(location);
                 for (i, data) in borrow_set.iter_enumerated() {
                     if borrow_of_local_data(data.borrowed_place) {
-                        self.all_facts.loan_invalidated_at.push((start, i));
+                        self.facts.loan_invalidated_at.push((start, i));
                     }
                 }
             }
@@ -409,7 +409,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
     /// Generates a new `loan_invalidated_at(L, B)` fact.
     fn emit_loan_invalidated_at(&mut self, b: BorrowIndex, l: Location) {
         let lidx = self.location_table.start_index(l);
-        self.all_facts.loan_invalidated_at.push((lidx, b));
+        self.facts.loan_invalidated_at.push((lidx, b));
     }
 
     fn check_activations(&mut self, location: Location) {
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs
index 68e0865ab82..fdde9fa0476 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs
@@ -14,12 +14,12 @@ use crate::places_conflict;
 /// Emit `loan_killed_at` and `cfg_edge` facts at the same time.
 pub(super) fn emit_loan_kills<'tcx>(
     tcx: TyCtxt<'tcx>,
-    all_facts: &mut AllFacts,
-    location_table: &LocationTable,
+    facts: &mut AllFacts,
     body: &Body<'tcx>,
+    location_table: &LocationTable,
     borrow_set: &BorrowSet<'tcx>,
 ) {
-    let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, all_facts, body };
+    let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, facts, body };
     for (bb, data) in body.basic_blocks.iter_enumerated() {
         visitor.visit_basic_block_data(bb, data);
     }
@@ -27,7 +27,7 @@ pub(super) fn emit_loan_kills<'tcx>(
 
 struct LoanKillsGenerator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    all_facts: &'a mut AllFacts,
+    facts: &'a mut AllFacts,
     location_table: &'a LocationTable,
     borrow_set: &'a BorrowSet<'tcx>,
     body: &'a Body<'tcx>,
@@ -36,12 +36,12 @@ struct LoanKillsGenerator<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> {
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         // Also record CFG facts here.
-        self.all_facts.cfg_edge.push((
+        self.facts.cfg_edge.push((
             self.location_table.start_index(location),
             self.location_table.mid_index(location),
         ));
 
-        self.all_facts.cfg_edge.push((
+        self.facts.cfg_edge.push((
             self.location_table.mid_index(location),
             self.location_table.start_index(location.successor_within_block()),
         ));
@@ -63,15 +63,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> {
 
     fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
         // Also record CFG facts here.
-        self.all_facts.cfg_edge.push((
+        self.facts.cfg_edge.push((
             self.location_table.start_index(location),
             self.location_table.mid_index(location),
         ));
 
         let successor_blocks = terminator.successors();
-        self.all_facts.cfg_edge.reserve(successor_blocks.size_hint().0);
+        self.facts.cfg_edge.reserve(successor_blocks.size_hint().0);
         for successor_block in successor_blocks {
-            self.all_facts.cfg_edge.push((
+            self.facts.cfg_edge.push((
                 self.location_table.mid_index(location),
                 self.location_table.start_index(successor_block.start_location()),
             ));
@@ -128,7 +128,7 @@ impl<'tcx> LoanKillsGenerator<'_, 'tcx> {
 
                         if places_conflict {
                             let location_index = self.location_table.mid_index(location);
-                            self.all_facts.loan_killed_at.push((borrow_index, location_index));
+                            self.facts.loan_killed_at.push((borrow_index, location_index));
                         }
                     }
                 }
@@ -140,9 +140,9 @@ impl<'tcx> LoanKillsGenerator<'_, 'tcx> {
     fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
         if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
             let location_index = self.location_table.mid_index(location);
-            self.all_facts.loan_killed_at.reserve(borrow_indices.len());
+            self.facts.loan_killed_at.reserve(borrow_indices.len());
             for &borrow_index in borrow_indices {
-                self.all_facts.loan_killed_at.push((borrow_index, location_index));
+                self.facts.loan_killed_at.push((borrow_index, location_index));
             }
         }
     }
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
index 9fccc00bdaf..60fd2afe63e 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
@@ -3,16 +3,23 @@
 //! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature
 //! parity.
 
-use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK};
-use rustc_middle::ty::TyCtxt;
+use std::iter;
+
+use either::Either;
+use rustc_middle::mir::{Body, Local, LocalKind, Location, START_BLOCK};
+use rustc_middle::ty::{GenericArg, TyCtxt};
 use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
 use tracing::debug;
 
 use crate::borrow_set::BorrowSet;
+use crate::constraints::OutlivesConstraint;
 use crate::facts::{AllFacts, PoloniusRegionVid};
 use crate::location::LocationTable;
+use crate::type_check::MirTypeckRegionConstraints;
 use crate::type_check::free_region_relations::UniversalRegionRelations;
+use crate::universal_regions::UniversalRegions;
 
+mod accesses;
 mod loan_invalidations;
 mod loan_kills;
 
@@ -22,6 +29,8 @@ mod loan_kills;
 /// - CFG points and edges
 /// - loan kills
 /// - loan invalidations
+/// - access facts such as variable definitions, uses, drops, and path accesses
+/// - outlives constraints
 ///
 /// The rest of the facts are emitted during typeck and liveness.
 pub(crate) fn emit_facts<'tcx>(
@@ -30,34 +39,42 @@ pub(crate) fn emit_facts<'tcx>(
     location_table: &LocationTable,
     body: &Body<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
-    move_data: &MoveData<'_>,
-    universal_region_relations: &UniversalRegionRelations<'_>,
+    move_data: &MoveData<'tcx>,
+    universal_region_relations: &UniversalRegionRelations<'tcx>,
+    constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
-    let Some(all_facts) = all_facts else {
+    let Some(facts) = all_facts else {
         // We don't do anything if there are no facts to fill.
         return;
     };
     let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
-    emit_move_facts(all_facts, move_data, location_table, body);
-    emit_universal_region_facts(all_facts, borrow_set, universal_region_relations);
-    emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
-    emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
+    emit_move_facts(facts, body, location_table, move_data);
+    emit_universal_region_facts(facts, borrow_set, universal_region_relations);
+    loan_kills::emit_loan_kills(tcx, facts, body, location_table, borrow_set);
+    loan_invalidations::emit_loan_invalidations(tcx, facts, body, location_table, borrow_set);
+    accesses::emit_access_facts(
+        tcx,
+        facts,
+        body,
+        location_table,
+        move_data,
+        &universal_region_relations.universal_regions,
+    );
+    emit_outlives_facts(facts, location_table, constraints);
 }
 
 /// Emit facts needed for move/init analysis: moves and assignments.
 fn emit_move_facts(
-    all_facts: &mut AllFacts,
-    move_data: &MoveData<'_>,
-    location_table: &LocationTable,
+    facts: &mut AllFacts,
     body: &Body<'_>,
+    location_table: &LocationTable,
+    move_data: &MoveData<'_>,
 ) {
-    all_facts
-        .path_is_var
-        .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
+    facts.path_is_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
 
     for (child, move_path) in move_data.move_paths.iter_enumerated() {
         if let Some(parent) = move_path.parent {
-            all_facts.child_path.push((child, parent));
+            facts.child_path.push((child, parent));
         }
     }
 
@@ -83,14 +100,14 @@ fn emit_move_facts(
                         // The initialization happened in (or rather, when arriving at)
                         // the successors, but not in the unwind block.
                         let first_statement = Location { block: successor, statement_index: 0 };
-                        all_facts
+                        facts
                             .path_assigned_at_base
                             .push((init.path, location_table.start_index(first_statement)));
                     }
                 } else {
                     // In all other cases, the initialization just happens at the
                     // midpoint, like any other effect.
-                    all_facts
+                    facts
                         .path_assigned_at_base
                         .push((init.path, location_table.mid_index(location)));
                 }
@@ -98,7 +115,7 @@ fn emit_move_facts(
             // Arguments are initialized on function entry
             InitLocation::Argument(local) => {
                 assert!(body.local_kind(local) == LocalKind::Arg);
-                all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
+                facts.path_assigned_at_base.push((init.path, fn_entry_start));
             }
         }
     }
@@ -107,20 +124,20 @@ fn emit_move_facts(
         if body.local_kind(local) != LocalKind::Arg {
             // Non-arguments start out deinitialised; we simulate this with an
             // initial move:
-            all_facts.path_moved_at_base.push((path, fn_entry_start));
+            facts.path_moved_at_base.push((path, fn_entry_start));
         }
     }
 
     // moved_out_at
     // deinitialisation is assumed to always happen!
-    all_facts
+    facts
         .path_moved_at_base
         .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
 }
 
 /// Emit universal regions facts, and their relations.
 fn emit_universal_region_facts(
-    all_facts: &mut AllFacts,
+    facts: &mut AllFacts,
     borrow_set: &BorrowSet<'_>,
     universal_region_relations: &UniversalRegionRelations<'_>,
 ) {
@@ -131,7 +148,7 @@ fn emit_universal_region_facts(
     //   added to the existing number of loans, as if they succeeded them in the set.
     //
     let universal_regions = &universal_region_relations.universal_regions;
-    all_facts
+    facts
         .universal_region
         .extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
     let borrow_count = borrow_set.len();
@@ -144,7 +161,7 @@ fn emit_universal_region_facts(
     for universal_region in universal_regions.universal_regions_iter() {
         let universal_region_idx = universal_region.index();
         let placeholder_loan_idx = borrow_count + universal_region_idx;
-        all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
+        facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
     }
 
     // 2: the universal region relations `outlives` constraints are emitted as
@@ -156,29 +173,51 @@ fn emit_universal_region_facts(
                      fr1={:?}, fr2={:?}",
                 fr1, fr2
             );
-            all_facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
+            facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
         }
     }
 }
 
-/// Emit facts about loan invalidations.
-fn emit_loan_invalidations_facts<'tcx>(
-    all_facts: &mut AllFacts,
+/// For every potentially drop()-touched region `region` in `local`'s type
+/// (`kind`), emit a `drop_of_var_derefs_origin(local, origin)` fact.
+pub(crate) fn emit_drop_facts<'tcx>(
     tcx: TyCtxt<'tcx>,
-    location_table: &LocationTable,
-    body: &Body<'tcx>,
-    borrow_set: &BorrowSet<'tcx>,
+    local: Local,
+    kind: &GenericArg<'tcx>,
+    universal_regions: &UniversalRegions<'tcx>,
+    all_facts: &mut Option<AllFacts>,
 ) {
-    loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set);
+    debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind);
+    let Some(facts) = all_facts.as_mut() else { return };
+    let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
+    tcx.for_each_free_region(kind, |drop_live_region| {
+        let region_vid = universal_regions.to_region_vid(drop_live_region);
+        facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
+    });
 }
 
-/// Emit facts about CFG points and edges, as well as locations where loans are killed.
-fn emit_cfg_and_loan_kills_facts<'tcx>(
-    all_facts: &mut AllFacts,
-    tcx: TyCtxt<'tcx>,
+/// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive
+/// closure.
+fn emit_outlives_facts<'tcx>(
+    facts: &mut AllFacts,
     location_table: &LocationTable,
-    body: &Body<'tcx>,
-    borrow_set: &BorrowSet<'tcx>,
+    constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
-    loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set);
+    facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map(
+        |constraint: &OutlivesConstraint<'_>| {
+            if let Some(from_location) = constraint.locations.from_location() {
+                Either::Left(iter::once((
+                    constraint.sup.into(),
+                    constraint.sub.into(),
+                    location_table.mid_index(from_location),
+                )))
+            } else {
+                Either::Right(
+                    location_table.all_points().map(move |location| {
+                        (constraint.sup.into(), constraint.sub.into(), location)
+                    }),
+                )
+            }
+        },
+    ));
 }
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 05e4a176a6d..683293bf828 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -17,7 +17,6 @@ use crate::region_infer::values::LivenessValues;
 use crate::universal_regions::UniversalRegions;
 
 mod local_use_map;
-mod polonius;
 mod trace;
 
 /// Combines liveness analysis with initialization analysis to
@@ -45,8 +44,6 @@ pub(super) fn generate<'a, 'tcx>(
     let (relevant_live_locals, boring_locals) =
         compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
 
-    polonius::emit_access_facts(typeck, body, move_data);
-
     trace::trace(
         typeck,
         body,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
deleted file mode 100644
index 5ffba94ee68..00000000000
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ /dev/null
@@ -1,123 +0,0 @@
-use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{Body, Local, Location, Place};
-use rustc_middle::ty::GenericArg;
-use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
-use tracing::debug;
-
-use super::TypeChecker;
-use crate::def_use::{self, DefUse};
-use crate::location::{LocationIndex, LocationTable};
-
-type VarPointRelation = Vec<(Local, LocationIndex)>;
-type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
-
-/// Emit polonius facts for variable defs, uses, drops, and path accesses.
-pub(super) fn emit_access_facts<'a, 'tcx>(
-    typeck: &mut TypeChecker<'a, 'tcx>,
-    body: &Body<'tcx>,
-    move_data: &MoveData<'tcx>,
-) {
-    if let Some(facts) = typeck.all_facts.as_mut() {
-        debug!("emit_access_facts()");
-
-        let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
-        let location_table = typeck.location_table;
-
-        let mut extractor = AccessFactsExtractor {
-            var_defined_at: &mut facts.var_defined_at,
-            var_used_at: &mut facts.var_used_at,
-            var_dropped_at: &mut facts.var_dropped_at,
-            path_accessed_at_base: &mut facts.path_accessed_at_base,
-            location_table,
-            move_data,
-        };
-        extractor.visit_body(body);
-
-        for (local, local_decl) in body.local_decls.iter_enumerated() {
-            debug!(
-                "add use_of_var_derefs_origin facts - local={:?}, type={:?}",
-                local, local_decl.ty
-            );
-            let universal_regions = &typeck.universal_regions;
-            typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
-                let region_vid = universal_regions.to_region_vid(region);
-                facts.use_of_var_derefs_origin.push((local, region_vid.into()));
-            });
-        }
-    }
-}
-
-/// For every potentially drop()-touched region `region` in `local`'s type
-/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
-pub(super) fn emit_drop_facts<'tcx>(
-    typeck: &mut TypeChecker<'_, 'tcx>,
-    local: Local,
-    kind: &GenericArg<'tcx>,
-) {
-    debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind);
-    if let Some(facts) = typeck.all_facts.as_mut() {
-        let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
-        let universal_regions = &typeck.universal_regions;
-        typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
-            let region_vid = universal_regions.to_region_vid(drop_live_region);
-            facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
-        });
-    }
-}
-
-/// MIR visitor extracting point-wise facts about accesses.
-struct AccessFactsExtractor<'a, 'tcx> {
-    var_defined_at: &'a mut VarPointRelation,
-    var_used_at: &'a mut VarPointRelation,
-    location_table: &'a LocationTable,
-    var_dropped_at: &'a mut VarPointRelation,
-    move_data: &'a MoveData<'tcx>,
-    path_accessed_at_base: &'a mut PathPointRelation,
-}
-
-impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
-    fn location_to_index(&self, location: Location) -> LocationIndex {
-        self.location_table.mid_index(location)
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
-    fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
-        match def_use::categorize(context) {
-            Some(DefUse::Def) => {
-                debug!("AccessFactsExtractor - emit def");
-                self.var_defined_at.push((local, self.location_to_index(location)));
-            }
-            Some(DefUse::Use) => {
-                debug!("AccessFactsExtractor - emit use");
-                self.var_used_at.push((local, self.location_to_index(location)));
-            }
-            Some(DefUse::Drop) => {
-                debug!("AccessFactsExtractor - emit drop");
-                self.var_dropped_at.push((local, self.location_to_index(location)));
-            }
-            _ => (),
-        }
-    }
-
-    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
-        self.super_place(place, context, location);
-
-        match context {
-            PlaceContext::NonMutatingUse(_)
-            | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
-                let path = match self.move_data.rev_lookup.find(place.as_ref()) {
-                    LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
-                    _ => {
-                        // There's no path access to emit.
-                        return;
-                    }
-                };
-                debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
-                self.path_accessed_at_base.push((path, self.location_to_index(location)));
-            }
-
-            _ => {}
-        }
-    }
-}
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 539d3f97a63..f510d193dd9 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -15,9 +15,9 @@ use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, Type
 use tracing::debug;
 
 use crate::location::RichLocation;
+use crate::polonius;
 use crate::region_infer::values::{self, LiveLoans};
 use crate::type_check::liveness::local_use_map::LocalUseMap;
-use crate::type_check::liveness::polonius;
 use crate::type_check::{NormalizeLocation, TypeChecker};
 
 /// This is the heart of the liveness computation. For each variable X
@@ -590,7 +590,13 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         // the destructor and must be live at this point.
         for &kind in &drop_data.dropck_result.kinds {
             Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
-            polonius::emit_drop_facts(self.typeck, dropped_local, &kind);
+            polonius::legacy::emit_drop_facts(
+                self.typeck.tcx(),
+                dropped_local,
+                &kind,
+                self.typeck.universal_regions,
+                self.typeck.all_facts,
+            );
         }
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 90d327b0ad2..de0804b0189 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -3,7 +3,6 @@
 use std::rc::Rc;
 use std::{fmt, iter, mem};
 
-use either::Either;
 use rustc_abi::{FIRST_VARIANT, FieldIdx};
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -107,7 +106,6 @@ mod relate_tys;
 /// # Parameters
 ///
 /// - `infcx` -- inference context to use
-/// - `param_env` -- parameter environment to use for trait solving
 /// - `body` -- MIR body to type-check
 /// - `promoted` -- map of promoted constants within `body`
 /// - `universal_regions` -- the universal regions from `body`s function signature
@@ -155,7 +153,7 @@ pub(crate) fn type_check<'a, 'tcx>(
 
     debug!(?normalized_inputs_and_output);
 
-    let mut checker = TypeChecker {
+    let mut typeck = TypeChecker {
         infcx,
         last_span: body.span,
         body,
@@ -171,24 +169,22 @@ pub(crate) fn type_check<'a, 'tcx>(
         constraints: &mut constraints,
     };
 
-    checker.check_user_type_annotations();
+    typeck.check_user_type_annotations();
 
-    let mut verifier = TypeVerifier { cx: &mut checker, promoted, last_span: body.span };
+    let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
     verifier.visit_body(body);
 
-    checker.typeck_mir(body);
-    checker.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
-    checker.check_signature_annotation(body);
+    typeck.typeck_mir(body);
+    typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
+    typeck.check_signature_annotation(body);
 
-    liveness::generate(&mut checker, body, &elements, flow_inits, move_data);
+    liveness::generate(&mut typeck, body, &elements, flow_inits, move_data);
 
-    translate_outlives_facts(&mut checker);
-    let opaque_type_values = infcx.take_opaque_types();
-
-    let opaque_type_values = opaque_type_values
+    let opaque_type_values = infcx
+        .take_opaque_types()
         .into_iter()
         .map(|(opaque_type_key, decl)| {
-            let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
+            let _: Result<_, ErrorGuaranteed> = typeck.fully_perform_op(
                 Locations::All(body.span),
                 ConstraintCategory::OpaqueType,
                 CustomTypeOp::new(
@@ -218,11 +214,11 @@ pub(crate) fn type_check<'a, 'tcx>(
                     match region.kind() {
                         ty::ReVar(_) => region,
                         ty::RePlaceholder(placeholder) => {
-                            checker.constraints.placeholder_region(infcx, placeholder)
+                            typeck.constraints.placeholder_region(infcx, placeholder)
                         }
                         _ => ty::Region::new_var(
                             infcx.tcx,
-                            checker.universal_regions.to_region_vid(region),
+                            typeck.universal_regions.to_region_vid(region),
                         ),
                     }
                 });
@@ -234,30 +230,6 @@ pub(crate) fn type_check<'a, 'tcx>(
     MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
 }
 
-fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
-    if let Some(facts) = typeck.all_facts {
-        let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
-        let location_table = typeck.location_table;
-        facts.subset_base.extend(
-            typeck.constraints.outlives_constraints.outlives().iter().flat_map(
-                |constraint: &OutlivesConstraint<'_>| {
-                    if let Some(from_location) = constraint.locations.from_location() {
-                        Either::Left(iter::once((
-                            constraint.sup.into(),
-                            constraint.sub.into(),
-                            location_table.mid_index(from_location),
-                        )))
-                    } else {
-                        Either::Right(location_table.all_points().map(move |location| {
-                            (constraint.sup.into(), constraint.sub.into(), location)
-                        }))
-                    }
-                },
-            ),
-        );
-    }
-}
-
 #[track_caller]
 fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
     // We sometimes see MIR failures (notably predicate failures) due to
@@ -276,7 +248,7 @@ enum FieldAccessError {
 /// type, calling `span_mirbug` and returning an error type if there
 /// is a problem.
 struct TypeVerifier<'a, 'b, 'tcx> {
-    cx: &'a mut TypeChecker<'b, 'tcx>,
+    typeck: &'a mut TypeChecker<'b, 'tcx>,
     promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
     last_span: Span,
 }
@@ -298,9 +270,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         self.super_const_operand(constant, location);
         let ty = self.sanitize_type(constant, constant.const_.ty());
 
-        self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
-            let live_region_vid = self.cx.universal_regions.to_region_vid(live_region);
-            self.cx.constraints.liveness_constraints.add_location(live_region_vid, location);
+        self.typeck.infcx.tcx.for_each_free_region(&ty, |live_region| {
+            let live_region_vid = self.typeck.universal_regions.to_region_vid(live_region);
+            self.typeck.constraints.liveness_constraints.add_location(live_region_vid, location);
         });
 
         // HACK(compiler-errors): Constants that are gathered into Body.required_consts
@@ -312,14 +284,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         };
 
         if let Some(annotation_index) = constant.user_ty {
-            if let Err(terr) = self.cx.relate_type_and_user_type(
+            if let Err(terr) = self.typeck.relate_type_and_user_type(
                 constant.const_.ty(),
                 ty::Invariant,
                 &UserTypeProjection { base: annotation_index, projs: vec![] },
                 locations,
                 ConstraintCategory::Boring,
             ) {
-                let annotation = &self.cx.user_type_annotations[annotation_index];
+                let annotation = &self.typeck.user_type_annotations[annotation_index];
                 span_mirbug!(
                     self,
                     constant,
@@ -348,9 +320,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                                      promoted: &Body<'tcx>,
                                      ty,
                                      san_ty| {
-                        if let Err(terr) =
-                            verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring)
-                        {
+                        if let Err(terr) = verifier.typeck.eq_types(
+                            ty,
+                            san_ty,
+                            locations,
+                            ConstraintCategory::Boring,
+                        ) {
                             span_mirbug!(
                                 verifier,
                                 promoted,
@@ -368,21 +343,21 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     let promoted_ty = promoted_body.return_ty();
                     check_err(self, promoted_body, ty, promoted_ty);
                 } else {
-                    self.cx.ascribe_user_type(
+                    self.typeck.ascribe_user_type(
                         constant.const_.ty(),
                         ty::UserType::new(ty::UserTypeKind::TypeOf(uv.def, UserArgs {
                             args: uv.args,
                             user_self_ty: None,
                         })),
-                        locations.span(self.cx.body),
+                        locations.span(self.typeck.body),
                     );
                 }
             } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
                 let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
-                let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
+                let normalized_ty = self.typeck.normalize(unnormalized_ty, locations);
                 let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
 
-                if let Err(terr) = self.cx.eq_types(
+                if let Err(terr) = self.typeck.eq_types(
                     literal_ty,
                     normalized_ty,
                     locations,
@@ -394,7 +369,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
             if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
                 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
-                self.cx.normalize_and_prove_instantiated_predicates(
+                self.typeck.normalize_and_prove_instantiated_predicates(
                     def_id,
                     instantiated_predicates,
                     locations,
@@ -404,7 +379,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
                     Some(DefKind::Impl { of_trait: true })
                 ));
-                self.cx.prove_predicates(
+                self.typeck.prove_predicates(
                     args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
                     locations,
                     ConstraintCategory::Boring,
@@ -438,7 +413,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     local_decl.ty
                 };
 
-                if let Err(terr) = self.cx.relate_type_and_user_type(
+                if let Err(terr) = self.typeck.relate_type_and_user_type(
                     ty,
                     ty::Invariant,
                     user_ty,
@@ -468,11 +443,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
 impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
     fn body(&self) -> &Body<'tcx> {
-        self.cx.body
+        self.typeck.body
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
-        self.cx.infcx.tcx
+        self.typeck.infcx.tcx
     }
 
     fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -522,7 +497,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             // whether the bounds fully apply: in effect, the rule is
             // that if a value of some type could implement `Copy`, then
             // it must.
-            self.cx.prove_trait_ref(
+            self.typeck.prove_trait_ref(
                 trait_ref,
                 location.to_locations(),
                 ConstraintCategory::CopyBound,
@@ -537,7 +512,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // checker on the promoted MIR, then transfer the constraints back to
         // the main MIR, changing the locations to the provided location.
 
-        let parent_body = mem::replace(&mut self.cx.body, promoted_body);
+        let parent_body = mem::replace(&mut self.typeck.body, promoted_body);
 
         // Use new sets of constraints and closure bounds so that we can
         // modify their locations.
@@ -548,18 +523,18 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // Don't try to add borrow_region facts for the promoted MIR
 
         let mut swap_constraints = |this: &mut Self| {
-            mem::swap(this.cx.all_facts, all_facts);
-            mem::swap(&mut this.cx.constraints.outlives_constraints, &mut constraints);
-            mem::swap(&mut this.cx.constraints.liveness_constraints, &mut liveness_constraints);
+            mem::swap(this.typeck.all_facts, all_facts);
+            mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints);
+            mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints);
         };
 
         swap_constraints(self);
 
         self.visit_body(promoted_body);
 
-        self.cx.typeck_mir(promoted_body);
+        self.typeck.typeck_mir(promoted_body);
 
-        self.cx.body = parent_body;
+        self.typeck.body = parent_body;
         // Merge the outlives constraints back in, at the given location.
         swap_constraints(self);
 
@@ -575,7 +550,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 // temporary from the user's point of view.
                 constraint.category = ConstraintCategory::Boring;
             }
-            self.cx.constraints.outlives_constraints.push(constraint)
+            self.typeck.constraints.outlives_constraints.push(constraint)
         }
         // If the region is live at least one location in the promoted MIR,
         // then add a liveness constraint to the main MIR for this region
@@ -585,7 +560,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // unordered.
         #[allow(rustc::potential_query_instability)]
         for region in liveness_constraints.live_regions_unordered() {
-            self.cx.constraints.liveness_constraints.add_location(region, location);
+            self.typeck.constraints.liveness_constraints.add_location(region, location);
         }
     }
 
@@ -669,13 +644,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             },
             ProjectionElem::Field(field, fty) => {
                 let fty = self.sanitize_type(place, fty);
-                let fty = self.cx.normalize(fty, location);
+                let fty = self.typeck.normalize(fty, location);
                 match self.field_ty(place, base, field, location) {
                     Ok(ty) => {
-                        let ty = self.cx.normalize(ty, location);
+                        let ty = self.typeck.normalize(ty, location);
                         debug!(?fty, ?ty);
 
-                        if let Err(terr) = self.cx.relate_types(
+                        if let Err(terr) = self.typeck.relate_types(
                             ty,
                             self.get_ambient_variance(context),
                             fty,
@@ -707,8 +682,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             }
             ProjectionElem::OpaqueCast(ty) => {
                 let ty = self.sanitize_type(place, ty);
-                let ty = self.cx.normalize(ty, location);
-                self.cx
+                let ty = self.typeck.normalize(ty, location);
+                self.typeck
                     .relate_types(
                         ty,
                         self.get_ambient_variance(context),
@@ -817,7 +792,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         };
 
         if let Some(field) = variant.fields.get(field) {
-            Ok(self.cx.normalize(field.ty(tcx, args), location))
+            Ok(self.typeck.normalize(field.ty(tcx, args), location))
         } else {
             Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
         }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
deleted file mode 100644
index c5d1ebdfe7c..00000000000
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-use rustc_data_structures::captures::Captures;
-use rustc_middle::mir::coverage::{
-    CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op,
-    SourceRegion,
-};
-
-use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind};
-
-pub(crate) struct FunctionCoverage<'tcx> {
-    pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo,
-    /// If `None`, the corresponding function is unused.
-    ids_info: Option<&'tcx CoverageIdsInfo>,
-}
-
-impl<'tcx> FunctionCoverage<'tcx> {
-    pub(crate) fn new_used(
-        function_coverage_info: &'tcx FunctionCoverageInfo,
-        ids_info: &'tcx CoverageIdsInfo,
-    ) -> Self {
-        Self { function_coverage_info, ids_info: Some(ids_info) }
-    }
-
-    pub(crate) fn new_unused(function_coverage_info: &'tcx FunctionCoverageInfo) -> Self {
-        Self { function_coverage_info, ids_info: None }
-    }
-
-    /// Returns true for a used (called) function, and false for an unused function.
-    pub(crate) fn is_used(&self) -> bool {
-        self.ids_info.is_some()
-    }
-
-    /// Return the source hash, generated from the HIR node structure, and used to indicate whether
-    /// or not the source code structure changed between different compilations.
-    pub(crate) fn source_hash(&self) -> u64 {
-        if self.is_used() { self.function_coverage_info.function_source_hash } else { 0 }
-    }
-
-    /// Convert this function's coverage expression data into a form that can be
-    /// passed through FFI to LLVM.
-    pub(crate) fn counter_expressions(
-        &self,
-    ) -> impl Iterator<Item = CounterExpression> + ExactSizeIterator + Captures<'_> {
-        // We know that LLVM will optimize out any unused expressions before
-        // producing the final coverage map, so there's no need to do the same
-        // thing on the Rust side unless we're confident we can do much better.
-        // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
-
-        self.function_coverage_info.expressions.iter().map(move |&Expression { lhs, op, rhs }| {
-            CounterExpression {
-                lhs: self.counter_for_term(lhs),
-                kind: match op {
-                    Op::Add => ExprKind::Add,
-                    Op::Subtract => ExprKind::Subtract,
-                },
-                rhs: self.counter_for_term(rhs),
-            }
-        })
-    }
-
-    /// Converts this function's coverage mappings into an intermediate form
-    /// that will be used by `mapgen` when preparing for FFI.
-    pub(crate) fn counter_regions(
-        &self,
-    ) -> impl Iterator<Item = (MappingKind, &SourceRegion)> + ExactSizeIterator {
-        self.function_coverage_info.mappings.iter().map(move |mapping| {
-            let Mapping { kind, source_region } = mapping;
-            let kind =
-                kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term });
-            (kind, source_region)
-        })
-    }
-
-    fn counter_for_term(&self, term: CovTerm) -> Counter {
-        if self.is_zero_term(term) { Counter::ZERO } else { Counter::from_term(term) }
-    }
-
-    fn is_zero_term(&self, term: CovTerm) -> bool {
-        match self.ids_info {
-            Some(ids_info) => ids_info.is_zero_term(term),
-            // This function is unused, so all coverage counters/expressions are zero.
-            None => true,
-        }
-    }
-}
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 4f2af732527..ca334286200 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,6 +1,6 @@
 use std::iter;
 
-use itertools::Itertools as _;
+use itertools::Itertools;
 use rustc_abi::Align;
 use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
@@ -8,8 +8,8 @@ use rustc_codegen_ssa::traits::{
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_index::IndexVec;
+use rustc_middle::mir;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_middle::{bug, mir};
 use rustc_session::RemapFileNameExt;
 use rustc_session::config::RemapPathScopeComponents;
 use rustc_span::def_id::DefIdSet;
@@ -18,7 +18,6 @@ use tracing::debug;
 
 use crate::common::CodegenCx;
 use crate::coverageinfo::llvm_cov;
-use crate::coverageinfo::map_data::FunctionCoverage;
 use crate::coverageinfo::mapgen::covfun::prepare_covfun_record;
 use crate::llvm;
 
@@ -49,46 +48,40 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
 
     debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
 
-    // In order to show that unused functions have coverage counts of zero (0), LLVM requires the
-    // functions exist. Generate synthetic functions with a (required) single counter, and add the
-    // MIR `Coverage` code regions to the `function_coverage_map`, before calling
-    // `ctx.take_function_coverage_map()`.
-    if cx.codegen_unit.is_code_coverage_dead_code_cgu() {
-        add_unused_functions(cx);
-    }
-
     // FIXME(#132395): Can this be none even when coverage is enabled?
-    let function_coverage_map = match cx.coverage_cx {
-        Some(ref cx) => cx.take_function_coverage_map(),
+    let instances_used = match cx.coverage_cx {
+        Some(ref cx) => cx.instances_used.borrow(),
         None => return,
     };
-    if function_coverage_map.is_empty() {
-        // This CGU has no functions with coverage instrumentation.
-        return;
-    }
 
-    let all_file_names = function_coverage_map
-        .iter()
-        .map(|(_, fn_cov)| fn_cov.function_coverage_info.body_span)
-        .map(|span| span_file_name(tcx, span));
-    let global_file_table = GlobalFileTable::new(all_file_names);
+    // The order of entries in this global file table needs to be deterministic,
+    // and ideally should also be independent of the details of stable-hashing,
+    // because coverage tests snapshots (`.cov-map`) can observe the order and
+    // would need to be re-blessed if it changes. As long as those requirements
+    // are satisfied, the order can be arbitrary.
+    let mut global_file_table = GlobalFileTable::new();
 
-    // Encode all filenames referenced by coverage mappings in this CGU.
-    let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
-    // The `llvm-cov` tool uses this hash to associate each covfun record with
-    // its corresponding filenames table, since the final binary will typically
-    // contain multiple covmap records from different compilation units.
-    let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
-
-    let mut unused_function_names = Vec::new();
-
-    let covfun_records = function_coverage_map
-        .into_iter()
-        .filter_map(|(instance, function_coverage)| {
-            prepare_covfun_record(tcx, &global_file_table, instance, &function_coverage)
-        })
+    let mut covfun_records = instances_used
+        .iter()
+        .copied()
+        // Sort by symbol name, so that the global file table is built in an
+        // order that doesn't depend on the stable-hash-based order in which
+        // instances were visited during codegen.
+        .sorted_by_cached_key(|&instance| tcx.symbol_name(instance).name)
+        .filter_map(|instance| prepare_covfun_record(tcx, &mut global_file_table, instance, true))
         .collect::<Vec<_>>();
 
+    // In a single designated CGU, also prepare covfun records for functions
+    // in this crate that were instrumented for coverage, but are unused.
+    if cx.codegen_unit.is_code_coverage_dead_code_cgu() {
+        let mut unused_instances = gather_unused_function_instances(cx);
+        // Sort the unused instances by symbol name, for the same reason as the used ones.
+        unused_instances.sort_by_cached_key(|&instance| tcx.symbol_name(instance).name);
+        covfun_records.extend(unused_instances.into_iter().filter_map(|instance| {
+            prepare_covfun_record(tcx, &mut global_file_table, instance, false)
+        }));
+    }
+
     // If there are no covfun records for this CGU, don't generate a covmap record.
     // Emitting a covmap record without any covfun records causes `llvm-cov` to
     // fail when generating coverage reports, and if there are no covfun records
@@ -98,6 +91,15 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         return;
     }
 
+    // Encode all filenames referenced by coverage mappings in this CGU.
+    let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
+    // The `llvm-cov` tool uses this hash to associate each covfun record with
+    // its corresponding filenames table, since the final binary will typically
+    // contain multiple covmap records from different compilation units.
+    let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
+
+    let mut unused_function_names = vec![];
+
     for covfun in &covfun_records {
         unused_function_names.extend(covfun.mangled_function_name_if_unused());
 
@@ -137,22 +139,13 @@ struct GlobalFileTable {
 }
 
 impl GlobalFileTable {
-    fn new(all_file_names: impl IntoIterator<Item = Symbol>) -> Self {
-        // Collect all of the filenames into a set. Filenames usually come in
-        // contiguous runs, so we can dedup adjacent ones to save work.
-        let mut raw_file_table = all_file_names.into_iter().dedup().collect::<FxIndexSet<Symbol>>();
-
-        // Sort the file table by its actual string values, not the arbitrary
-        // ordering of its symbols.
-        raw_file_table.sort_unstable_by(|a, b| a.as_str().cmp(b.as_str()));
-
-        Self { raw_file_table }
+    fn new() -> Self {
+        Self { raw_file_table: FxIndexSet::default() }
     }
 
-    fn global_file_id_for_file_name(&self, file_name: Symbol) -> GlobalFileId {
-        let raw_id = self.raw_file_table.get_index_of(&file_name).unwrap_or_else(|| {
-            bug!("file name not found in prepared global file table: {file_name}");
-        });
+    fn global_file_id_for_file_name(&mut self, file_name: Symbol) -> GlobalFileId {
+        // Ensure the given file has a table entry, and get its index.
+        let (raw_id, _) = self.raw_file_table.insert_full(file_name);
         // The raw file table doesn't include an entry for the working dir
         // (which has ID 0), so add 1 to get the correct ID.
         GlobalFileId::from_usize(raw_id + 1)
@@ -264,39 +257,35 @@ fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_
 /// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
 /// We also end up adding their symbol names to a special global array that LLVM will include in
 /// its embedded coverage data.
-fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
+fn gather_unused_function_instances<'tcx>(cx: &CodegenCx<'_, 'tcx>) -> Vec<ty::Instance<'tcx>> {
     assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
 
     let tcx = cx.tcx;
     let usage = prepare_usage_sets(tcx);
 
     let is_unused_fn = |def_id: LocalDefId| -> bool {
-        let def_id = def_id.to_def_id();
-
-        // To be eligible for "unused function" mappings, a definition must:
-        // - Be function-like
+        // Usage sets expect `DefId`, so convert from `LocalDefId`.
+        let d: DefId = LocalDefId::to_def_id(def_id);
+        // To be potentially eligible for "unused function" mappings, a definition must:
+        // - Be eligible for coverage instrumentation
         // - Not participate directly in codegen (or have lost all its coverage statements)
         // - Not have any coverage statements inlined into codegenned functions
-        tcx.def_kind(def_id).is_fn_like()
-            && (!usage.all_mono_items.contains(&def_id)
-                || usage.missing_own_coverage.contains(&def_id))
-            && !usage.used_via_inlining.contains(&def_id)
+        tcx.is_eligible_for_coverage(def_id)
+            && (!usage.all_mono_items.contains(&d) || usage.missing_own_coverage.contains(&d))
+            && !usage.used_via_inlining.contains(&d)
     };
 
-    // Scan for unused functions that were instrumented for coverage.
-    for def_id in tcx.mir_keys(()).iter().copied().filter(|&def_id| is_unused_fn(def_id)) {
-        // Get the coverage info from MIR, skipping functions that were never instrumented.
-        let body = tcx.optimized_mir(def_id);
-        let Some(function_coverage_info) = body.function_coverage_info.as_deref() else { continue };
+    // FIXME(#79651): Consider trying to filter out dummy instantiations of
+    // unused generic functions from library crates, because they can produce
+    // "unused instantiation" in coverage reports even when they are actually
+    // used by some downstream crate in the same binary.
 
-        // FIXME(79651): Consider trying to filter out dummy instantiations of
-        // unused generic functions from library crates, because they can produce
-        // "unused instantiation" in coverage reports even when they are actually
-        // used by some downstream crate in the same binary.
-
-        debug!("generating unused fn: {def_id:?}");
-        add_unused_function_coverage(cx, def_id, function_coverage_info);
-    }
+    tcx.mir_keys(())
+        .iter()
+        .copied()
+        .filter(|&def_id| is_unused_fn(def_id))
+        .map(|def_id| make_dummy_instance(tcx, def_id))
+        .collect::<Vec<_>>()
 }
 
 struct UsageSets<'tcx> {
@@ -361,16 +350,11 @@ fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
     UsageSets { all_mono_items, used_via_inlining, missing_own_coverage }
 }
 
-fn add_unused_function_coverage<'tcx>(
-    cx: &CodegenCx<'_, 'tcx>,
-    def_id: LocalDefId,
-    function_coverage_info: &'tcx mir::coverage::FunctionCoverageInfo,
-) {
-    let tcx = cx.tcx;
-    let def_id = def_id.to_def_id();
+fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty::Instance<'tcx> {
+    let def_id = local_def_id.to_def_id();
 
     // Make a dummy instance that fills in all generics with placeholders.
-    let instance = ty::Instance::new(
+    ty::Instance::new(
         def_id,
         ty::GenericArgs::for_item(tcx, def_id, |param, _| {
             if let ty::GenericParamDefKind::Lifetime = param.kind {
@@ -379,9 +363,5 @@ fn add_unused_function_coverage<'tcx>(
                 tcx.mk_param_from_def(param)
             }
         }),
-    );
-
-    // An unused function's mappings will all be rewritten to map to zero.
-    let function_coverage = FunctionCoverage::new_unused(function_coverage_info);
-    cx.coverage_cx().function_coverage_map.borrow_mut().insert(instance, function_coverage);
+    )
 }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index 33e7a0f2f20..8e853f057be 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -11,13 +11,14 @@ use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
 };
 use rustc_middle::bug;
-use rustc_middle::mir::coverage::MappingKind;
+use rustc_middle::mir::coverage::{
+    CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op,
+};
 use rustc_middle::ty::{Instance, TyCtxt};
 use rustc_target::spec::HasTargetSpec;
 use tracing::debug;
 
 use crate::common::CodegenCx;
-use crate::coverageinfo::map_data::FunctionCoverage;
 use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, span_file_name};
 use crate::coverageinfo::{ffi, llvm_cov};
 use crate::llvm;
@@ -45,20 +46,25 @@ impl<'tcx> CovfunRecord<'tcx> {
 
 pub(crate) fn prepare_covfun_record<'tcx>(
     tcx: TyCtxt<'tcx>,
-    global_file_table: &GlobalFileTable,
+    global_file_table: &mut GlobalFileTable,
     instance: Instance<'tcx>,
-    function_coverage: &FunctionCoverage<'tcx>,
+    is_used: bool,
 ) -> Option<CovfunRecord<'tcx>> {
+    let fn_cov_info = tcx.instance_mir(instance.def).function_coverage_info.as_deref()?;
+    let ids_info = tcx.coverage_ids_info(instance.def);
+
+    let expressions = prepare_expressions(fn_cov_info, ids_info, is_used);
+
     let mut covfun = CovfunRecord {
         mangled_function_name: tcx.symbol_name(instance).name,
-        source_hash: function_coverage.source_hash(),
-        is_used: function_coverage.is_used(),
+        source_hash: if is_used { fn_cov_info.function_source_hash } else { 0 },
+        is_used,
         virtual_file_mapping: VirtualFileMapping::default(),
-        expressions: function_coverage.counter_expressions().collect::<Vec<_>>(),
+        expressions,
         regions: ffi::Regions::default(),
     };
 
-    fill_region_tables(tcx, global_file_table, function_coverage, &mut covfun);
+    fill_region_tables(tcx, global_file_table, fn_cov_info, ids_info, &mut covfun);
 
     if covfun.regions.has_no_regions() {
         if covfun.is_used {
@@ -72,20 +78,50 @@ pub(crate) fn prepare_covfun_record<'tcx>(
     Some(covfun)
 }
 
+/// Convert the function's coverage-counter expressions into a form suitable for FFI.
+fn prepare_expressions(
+    fn_cov_info: &FunctionCoverageInfo,
+    ids_info: &CoverageIdsInfo,
+    is_used: bool,
+) -> Vec<ffi::CounterExpression> {
+    // If any counters or expressions were removed by MIR opts, replace their
+    // terms with zero.
+    let counter_for_term = |term| {
+        if !is_used || ids_info.is_zero_term(term) {
+            ffi::Counter::ZERO
+        } else {
+            ffi::Counter::from_term(term)
+        }
+    };
+
+    // We know that LLVM will optimize out any unused expressions before
+    // producing the final coverage map, so there's no need to do the same
+    // thing on the Rust side unless we're confident we can do much better.
+    // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
+    fn_cov_info
+        .expressions
+        .iter()
+        .map(move |&Expression { lhs, op, rhs }| ffi::CounterExpression {
+            lhs: counter_for_term(lhs),
+            kind: match op {
+                Op::Add => ffi::ExprKind::Add,
+                Op::Subtract => ffi::ExprKind::Subtract,
+            },
+            rhs: counter_for_term(rhs),
+        })
+        .collect::<Vec<_>>()
+}
+
 /// Populates the mapping region tables in the current function's covfun record.
 fn fill_region_tables<'tcx>(
     tcx: TyCtxt<'tcx>,
-    global_file_table: &GlobalFileTable,
-    function_coverage: &FunctionCoverage<'tcx>,
+    global_file_table: &mut GlobalFileTable,
+    fn_cov_info: &'tcx FunctionCoverageInfo,
+    ids_info: &'tcx CoverageIdsInfo,
     covfun: &mut CovfunRecord<'tcx>,
 ) {
-    let counter_regions = function_coverage.counter_regions();
-    if counter_regions.is_empty() {
-        return;
-    }
-
     // Currently a function's mappings must all be in the same file as its body span.
-    let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span);
+    let file_name = span_file_name(tcx, fn_cov_info.body_span);
 
     // Look up the global file ID for that filename.
     let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
@@ -99,10 +135,14 @@ fn fill_region_tables<'tcx>(
 
     // For each counter/region pair in this function+file, convert it to a
     // form suitable for FFI.
-    for (mapping_kind, region) in counter_regions {
-        debug!("Adding counter {mapping_kind:?} to map for {region:?}");
-        let span = ffi::CoverageSpan::from_source_region(local_file_id, region);
-        match mapping_kind {
+    let is_zero_term = |term| !covfun.is_used || ids_info.is_zero_term(term);
+    for Mapping { kind, ref source_region } in &fn_cov_info.mappings {
+        // If the mapping refers to counters/expressions that were removed by
+        // MIR opts, replace those occurrences with zero.
+        let kind = kind.map_terms(|term| if is_zero_term(term) { CovTerm::Zero } else { term });
+
+        let span = ffi::CoverageSpan::from_source_region(local_file_id, source_region);
+        match kind {
             MappingKind::Code(term) => {
                 code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) });
             }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 82b6677e203..7311cd9d230 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -5,7 +5,7 @@ use rustc_abi::Size;
 use rustc_codegen_ssa::traits::{
     BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods, MiscCodegenMethods,
 };
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::layout::HasTyCtxt;
@@ -13,18 +13,16 @@ use tracing::{debug, instrument};
 
 use crate::builder::Builder;
 use crate::common::CodegenCx;
-use crate::coverageinfo::map_data::FunctionCoverage;
 use crate::llvm;
 
 pub(crate) mod ffi;
 mod llvm_cov;
-pub(crate) mod map_data;
 mod mapgen;
 
 /// Extra per-CGU context/state needed for coverage instrumentation.
 pub(crate) struct CguCoverageContext<'ll, 'tcx> {
     /// Coverage data for each instrumented function identified by DefId.
-    pub(crate) function_coverage_map: RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverage<'tcx>>>,
+    pub(crate) instances_used: RefCell<FxIndexSet<Instance<'tcx>>>,
     pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
     pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, Vec<&'ll llvm::Value>>>,
 
@@ -34,17 +32,13 @@ pub(crate) struct CguCoverageContext<'ll, 'tcx> {
 impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> {
     pub(crate) fn new() -> Self {
         Self {
-            function_coverage_map: Default::default(),
+            instances_used: RefCell::<FxIndexSet<_>>::default(),
             pgo_func_name_var_map: Default::default(),
             mcdc_condition_bitmap_map: Default::default(),
             covfun_section_name: Default::default(),
         }
     }
 
-    fn take_function_coverage_map(&self) -> FxIndexMap<Instance<'tcx>, FunctionCoverage<'tcx>> {
-        self.function_coverage_map.replace(FxIndexMap::default())
-    }
-
     /// LLVM use a temp value to record evaluated mcdc test vector of each decision, which is
     /// called condition bitmap. In order to handle nested decisions, several condition bitmaps can
     /// be allocated for a function body. These values are named `mcdc.addr.{i}` and are a 32-bit
@@ -157,12 +151,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
         // Mark the instance as used in this CGU, for coverage purposes.
         // This includes functions that were not partitioned into this CGU,
         // but were MIR-inlined into one of this CGU's functions.
-        coverage_cx.function_coverage_map.borrow_mut().entry(instance).or_insert_with(|| {
-            FunctionCoverage::new_used(
-                function_coverage_info,
-                bx.tcx.coverage_ids_info(instance.def),
-            )
-        });
+        coverage_cx.instances_used.borrow_mut().insert(instance);
 
         match *kind {
             CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!(
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 25d41462556..58fe3ec4b85 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1569,18 +1569,18 @@ impl DiagCtxtInner {
                 debug!(?diagnostic);
                 debug!(?self.emitted_diagnostics);
 
-                let already_emitted_sub = |sub: &mut Subdiag| {
+                let not_yet_emitted = |sub: &mut Subdiag| {
                     debug!(?sub);
                     if sub.level != OnceNote && sub.level != OnceHelp {
-                        return false;
+                        return true;
                     }
                     let mut hasher = StableHasher::new();
                     sub.hash(&mut hasher);
                     let diagnostic_hash = hasher.finish();
                     debug!(?diagnostic_hash);
-                    !self.emitted_diagnostics.insert(diagnostic_hash)
+                    self.emitted_diagnostics.insert(diagnostic_hash)
                 };
-                diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
+                diagnostic.children.retain_mut(not_yet_emitted);
                 if already_emitted {
                     let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
                     diagnostic.sub(Note, msg, MultiSpan::new());
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index 9b495c19990..50c64a9c947 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -205,7 +205,7 @@ impl EarlyLintPass for NonAsciiIdents {
                     (IdentifierType::Not_NFKC, "Not_NFKC"),
                 ] {
                     let codepoints: Vec<_> =
-                        chars.extract_if(|(_, ty)| *ty == Some(id_ty)).collect();
+                        chars.extract_if(.., |(_, ty)| *ty == Some(id_ty)).collect();
                     if codepoints.is_empty() {
                         continue;
                     }
@@ -217,7 +217,7 @@ impl EarlyLintPass for NonAsciiIdents {
                 }
 
                 let remaining = chars
-                    .extract_if(|(c, _)| !GeneralSecurityProfile::identifier_allowed(*c))
+                    .extract_if(.., |(c, _)| !GeneralSecurityProfile::identifier_allowed(*c))
                     .collect::<Vec<_>>();
                 if !remaining.is_empty() {
                     cx.emit_span_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index fe3bdb3a7b9..2ccc0d0dc02 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -544,7 +544,7 @@ impl<'tcx> Collector<'tcx> {
             // can move them to the end of the list below.
             let mut existing = self
                 .libs
-                .extract_if(|lib| {
+                .extract_if(.., |lib| {
                     if lib.name.as_str() == passed_lib.name {
                         // FIXME: This whole logic is questionable, whether modifiers are
                         // involved or not, library reordering and kind overriding without
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 604f1da26c6..406e732744b 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -309,7 +309,7 @@ pub fn suggest_constraining_type_params<'a>(
         let Some(param) = param else { return false };
 
         {
-            let mut sized_constraints = constraints.extract_if(|(_, def_id, _)| {
+            let mut sized_constraints = constraints.extract_if(.., |(_, def_id, _)| {
                 def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))
             });
             if let Some((_, def_id, _)) = sized_constraints.next() {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 368eb3c26c7..7cd56a8fb95 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2817,11 +2817,11 @@ fn show_candidates(
         path_strings.sort_by(|a, b| a.0.cmp(&b.0));
         path_strings.dedup_by(|a, b| a.0 == b.0);
         let core_path_strings =
-            path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
+            path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
         let std_path_strings =
-            path_strings.extract_if(|p| p.0.starts_with("std::")).collect::<Vec<_>>();
+            path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
         let foreign_crate_path_strings =
-            path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
+            path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
 
         // We list the `crate` local paths first.
         // Then we list the `std`/`core` paths.
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 85ea6a74d3c..1625f69158f 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -629,7 +629,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         // Try to filter out intrinsics candidates, as long as we have
         // some other candidates to suggest.
         let intrinsic_candidates: Vec<_> = candidates
-            .extract_if(|sugg| {
+            .extract_if(.., |sugg| {
                 let path = path_names_to_string(&sugg.path);
                 path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::")
             })
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
index 952a00c52a2..f763c37f535 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
@@ -13,8 +13,8 @@ pub(crate) fn target() -> Target {
         llvm_target: "powerpc64le-unknown-linux-musl".into(),
         metadata: crate::spec::TargetMetadata {
             description: Some("64-bit PowerPC Linux with musl 1.2.3, Little Endian".into()),
-            tier: Some(3),
-            host_tools: Some(false),
+            tier: Some(2),
+            host_tools: Some(true),
             std: Some(true),
         },
         pointer_width: 64,
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 069fab6a6e6..069d42d4018 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -447,7 +447,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     // This works fairly well because trait matching does not actually care about param-env
     // TypeOutlives predicates - these are normally used by regionck.
     let outlives_predicates: Vec<_> = predicates
-        .extract_if(|predicate| {
+        .extract_if(.., |predicate| {
             matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..))
         })
         .collect();