about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs120
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs18
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs20
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs196
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs22
-rw-r--r--compiler/rustc_middle/src/query/mod.rs10
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs20
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs61
10 files changed, 261 insertions, 242 deletions
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index e0af5653753..32f18419753 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -5,12 +5,13 @@ use crate::llvm;
 use llvm::coverageinfo::CounterMappingRegion;
 use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression};
 use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_hir::def_id::{DefId, DefIdSet};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefIdSet;
 use rustc_llvm::RustString;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::CodeRegion;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::Symbol;
 
 use std::ffi::CString;
 
@@ -46,7 +47,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
     // 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 !tcx.sess.instrument_coverage_except_unused_functions() {
+    if cx.codegen_unit.is_code_coverage_dead_code_cgu() {
         add_unused_functions(cx);
     }
 
@@ -271,26 +272,35 @@ fn save_function_record(
 /// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query
 /// `codegened_and_inlined_items`).
 ///
-/// *HOWEVER* the codegenned `DefId`s are partitioned across multiple `CodegenUnit`s (CGUs), and
-/// this function is processing a `function_coverage_map` for the functions (`Instance`/`DefId`)
-/// allocated to only one of those CGUs. We must NOT inject any unused functions's `CodeRegion`s
-/// more than once, so we have to pick a CGUs `function_coverage_map` into which the unused
-/// function will be inserted.
+/// These unused functions are then codegen'd in one of the CGUs which is marked as the
+/// "code coverage dead code cgu" during the partitioning process. This prevents us from generating
+/// code regions for the same function more than once which can lead to linker errors regarding
+/// duplicate symbols.
 fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
-    let tcx = cx.tcx;
+    assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
 
-    // FIXME(#79622): Can this solution be simplified and/or improved? Are there other sources
-    // of compiler state data that might help (or better sources that could be exposed, but
-    // aren't yet)?
+    let tcx = cx.tcx;
 
     let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics();
 
-    let all_def_ids: DefIdSet = tcx
+    let eligible_def_ids: DefIdSet = tcx
         .mir_keys(())
         .iter()
         .filter_map(|local_def_id| {
             let def_id = local_def_id.to_def_id();
-            if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) {
+            let kind = tcx.def_kind(def_id);
+            // `mir_keys` will give us `DefId`s for all kinds of things, not
+            // just "functions", like consts, statics, etc. Filter those out.
+            // If `ignore_unused_generics` was specified, filter out any
+            // generic functions from consideration as well.
+            if !matches!(
+                kind,
+                DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator
+            ) {
+                return None;
+            } else if ignore_unused_generics
+                && tcx.generics_of(def_id).requires_monomorphization(tcx)
+            {
                 return None;
             }
             Some(local_def_id.to_def_id())
@@ -299,79 +309,17 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
 
     let codegenned_def_ids = tcx.codegened_and_inlined_items(());
 
-    let mut unused_def_ids_by_file: FxHashMap<Symbol, Vec<DefId>> = FxHashMap::default();
-    for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) {
-        // Make sure the non-codegenned (unused) function has at least one MIR
-        // `Coverage` statement with a code region, and return its file name.
-        if let Some(non_codegenned_file_name) = tcx.covered_file_name(non_codegenned_def_id) {
-            let def_ids =
-                unused_def_ids_by_file.entry(*non_codegenned_file_name).or_insert_with(Vec::new);
-            def_ids.push(non_codegenned_def_id);
-        }
-    }
+    for &non_codegenned_def_id in eligible_def_ids.difference(codegenned_def_ids) {
+        let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id);
 
-    if unused_def_ids_by_file.is_empty() {
-        // There are no unused functions with file names to add (in any CGU)
-        return;
-    }
-
-    // Each `CodegenUnit` (CGU) has its own function_coverage_map, and generates a specific binary
-    // with its own coverage map.
-    //
-    // Each covered function `Instance` can be included in only one coverage map, produced from a
-    // specific function_coverage_map, from a specific CGU.
-    //
-    // Since unused functions did not generate code, they are not associated with any CGU yet.
-    //
-    // To avoid injecting the unused functions in multiple coverage maps (for multiple CGUs)
-    // determine which function_coverage_map has the responsibility for publishing unreachable
-    // coverage, based on file name: For each unused function, find the CGU that generates the
-    // first function (based on sorted `DefId`) from the same file.
-    //
-    // Add a new `FunctionCoverage` to the `function_coverage_map`, with unreachable code regions
-    // for each region in it's MIR.
-
-    // Convert the `HashSet` of `codegenned_def_ids` to a sortable vector, and sort them.
-    let mut sorted_codegenned_def_ids: Vec<DefId> = codegenned_def_ids.iter().copied().collect();
-    sorted_codegenned_def_ids.sort_unstable();
-
-    let mut first_covered_def_id_by_file: FxHashMap<Symbol, DefId> = FxHashMap::default();
-    for &def_id in sorted_codegenned_def_ids.iter() {
-        if let Some(covered_file_name) = tcx.covered_file_name(def_id) {
-            // Only add files known to have unused functions
-            if unused_def_ids_by_file.contains_key(covered_file_name) {
-                first_covered_def_id_by_file.entry(*covered_file_name).or_insert(def_id);
-            }
+        // If a function is marked `#[no_coverage]`, then skip generating a
+        // dead code stub for it.
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
+            debug!("skipping unused fn marked #[no_coverage]: {:?}", non_codegenned_def_id);
+            continue;
         }
-    }
-
-    // Get the set of def_ids with coverage regions, known by *this* CoverageContext.
-    let cgu_covered_def_ids: DefIdSet = match cx.coverage_context() {
-        Some(ctx) => ctx
-            .function_coverage_map
-            .borrow()
-            .keys()
-            .map(|&instance| instance.def.def_id())
-            .collect(),
-        None => return,
-    };
 
-    let cgu_covered_files: FxHashSet<Symbol> = first_covered_def_id_by_file
-        .iter()
-        .filter_map(
-            |(&file_name, def_id)| {
-                if cgu_covered_def_ids.contains(def_id) { Some(file_name) } else { None }
-            },
-        )
-        .collect();
-
-    // For each file for which this CGU is responsible for adding unused function coverage,
-    // get the `def_id`s for each unused function (if any), define a synthetic function with a
-    // single LLVM coverage counter, and add the function's coverage `CodeRegion`s. to the
-    // function_coverage_map.
-    for covered_file_name in cgu_covered_files {
-        for def_id in unused_def_ids_by_file.remove(&covered_file_name).into_iter().flatten() {
-            cx.define_unused_fn(def_id);
-        }
+        debug!("generating unused fn: {:?}", non_codegenned_def_id);
+        cx.define_unused_fn(non_codegenned_def_id);
     }
 }
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 5c13dfdc1b5..6c6ee363ea3 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -41,6 +41,6 @@ rustc_target = { path = "../rustc_target" }
 rustc_session = { path = "../rustc_session" }
 
 [dependencies.object]
-version = "0.26.2"
+version = "0.28.0"
 default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 79c24f0f172..6849533abc0 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -95,7 +95,7 @@ fn search_for_metadata<'a>(
         .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e))
 }
 
-fn create_object_file(sess: &Session) -> Option<write::Object> {
+fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
     let endianness = match sess.target.options.endian {
         Endian::Little => Endianness::Little,
         Endian::Big => Endianness::Big,
@@ -135,12 +135,24 @@ fn create_object_file(sess: &Session) -> Option<write::Object> {
         Architecture::Mips => {
             // copied from `mipsel-linux-gnu-gcc foo.c -c` and
             // inspecting the resulting `e_flags` field.
-            let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC;
+            let e_flags = elf::EF_MIPS_CPIC
+                | elf::EF_MIPS_PIC
+                | if sess.target.options.cpu.contains("r6") {
+                    elf::EF_MIPS_ARCH_32R6 | elf::EF_MIPS_NAN2008
+                } else {
+                    elf::EF_MIPS_ARCH_32R2
+                };
             file.flags = FileFlags::Elf { e_flags };
         }
         Architecture::Mips64 => {
             // copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
-            let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC;
+            let e_flags = elf::EF_MIPS_CPIC
+                | elf::EF_MIPS_PIC
+                | if sess.target.options.cpu.contains("r6") {
+                    elf::EF_MIPS_ARCH_64R6 | elf::EF_MIPS_NAN2008
+                } else {
+                    elf::EF_MIPS_ARCH_64R2
+                };
             file.flags = FileFlags::Elf { e_flags };
         }
         Architecture::Riscv64 if sess.target.options.features.contains("+d") => {
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index c2ef0b41e27..d5e65705b28 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -551,6 +551,22 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
             let predicate = predicate.subst(tcx, substs);
             debug!(?predicate);
 
+            let predicate = predicate.fold_with(&mut BottomUpFolder {
+                tcx,
+                ty_op: |ty| match *ty.kind() {
+                    // Replace all other mentions of the same opaque type with the hidden type,
+                    // as the bounds must hold on the hidden type after all.
+                    ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => {
+                        ty_var
+                    }
+                    // Instantiate nested instances of `impl Trait`.
+                    ty::Opaque(..) => self.instantiate_opaque_types_in_map(ty),
+                    _ => ty,
+                },
+                lt_op: |lt| lt,
+                ct_op: |ct| ct,
+            });
+
             // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
@@ -575,10 +591,6 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                     return tcx.ty_error();
                 }
             }
-            // Change the predicate to refer to the type variable,
-            // which will be the concrete type instead of the opaque type.
-            // This also instantiates nested instances of `impl Trait`.
-            let predicate = self.instantiate_opaque_types_in_map(predicate);
 
             let cause =
                 traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 3ec384193c3..85c0d28d5ea 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -218,40 +218,40 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for CrateMetadataRef<'a> {
     #[inline]
     fn blob(self) -> &'a MetadataBlob {
-        &self.blob
+        &self.cdata.blob
     }
     #[inline]
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
-        Some(*self)
+        Some(self)
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, &'tcx Session) {
     #[inline]
     fn blob(self) -> &'a MetadataBlob {
-        &self.0.blob
+        &self.0.cdata.blob
     }
     #[inline]
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
-        Some(*self.0)
+        Some(self.0)
     }
     #[inline]
     fn sess(self) -> Option<&'tcx Session> {
-        Some(&self.1)
+        Some(self.1)
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) {
     #[inline]
     fn blob(self) -> &'a MetadataBlob {
-        &self.0.blob
+        &self.0.cdata.blob
     }
     #[inline]
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
-        Some(*self.0)
+        Some(self.0)
     }
     #[inline]
     fn tcx(self) -> Option<TyCtxt<'tcx>> {
@@ -414,9 +414,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
             Ok(cdata
                 .root
                 .syntax_contexts
-                .get(&cdata, id)
+                .get(cdata, id)
                 .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname))
-                .decode((&cdata, sess)))
+                .decode((cdata, sess)))
         })
     }
 }
@@ -442,15 +442,15 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
             let expn_data = crate_data
                 .root
                 .expn_data
-                .get(&crate_data, index)
+                .get(crate_data, index)
                 .unwrap()
-                .decode((&crate_data, sess));
+                .decode((crate_data, sess));
             let expn_hash = crate_data
                 .root
                 .expn_hashes
-                .get(&crate_data, index)
+                .get(crate_data, index)
                 .unwrap()
-                .decode((&crate_data, sess));
+                .decode((crate_data, sess));
             (expn_data, expn_hash)
         });
         Ok(expn_id)
@@ -706,7 +706,7 @@ impl CrateRoot<'_> {
 }
 
 impl<'a, 'tcx> CrateMetadataRef<'a> {
-    fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
+    fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro {
         // DefIndex's in root.proc_macro_data have a one-to-one correspondence
         // with items in 'raw_proc_macros'.
         let pos = self
@@ -721,7 +721,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         &self.raw_proc_macros.unwrap()[pos]
     }
 
-    fn opt_item_ident(&self, item_index: DefIndex, sess: &Session) -> Option<Ident> {
+    fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> {
         let name = self.def_key(item_index).disambiguated_data.data.get_opt_name()?;
         let span = match self.root.tables.ident_span.get(self, item_index) {
             Some(lazy_span) => lazy_span.decode((self, sess)),
@@ -737,15 +737,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         Some(Ident::new(name, span))
     }
 
-    fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
+    fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident {
         self.opt_item_ident(item_index, sess).expect("no encoded ident for item")
     }
 
-    fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
+    fn maybe_kind(self, item_id: DefIndex) -> Option<EntryKind> {
         self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
     }
 
-    fn kind(&self, item_id: DefIndex) -> EntryKind {
+    fn kind(self, item_id: DefIndex) -> EntryKind {
         self.maybe_kind(item_id).unwrap_or_else(|| {
             bug!(
                 "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
@@ -756,7 +756,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         })
     }
 
-    fn def_kind(&self, item_id: DefIndex) -> DefKind {
+    fn def_kind(self, item_id: DefIndex) -> DefKind {
         self.root.tables.def_kind.get(self, item_id).map(|k| k.decode(self)).unwrap_or_else(|| {
             bug!(
                 "CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}",
@@ -767,7 +767,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         })
     }
 
-    fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
+    fn get_span(self, index: DefIndex, sess: &Session) -> Span {
         self.root
             .tables
             .span
@@ -776,7 +776,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, sess))
     }
 
-    fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
+    fn load_proc_macro(self, id: DefIndex, sess: &Session) -> SyntaxExtension {
         let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
             ProcMacro::CustomDerive { trait_name, attributes, client } => {
                 let helper_attrs =
@@ -807,7 +807,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         )
     }
 
-    fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
+    fn get_trait_def(self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
         match self.kind(item_id) {
             EntryKind::Trait(data) => {
                 let data = data.decode((self, sess));
@@ -837,7 +837,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_variant(
-        &self,
+        self,
         kind: &EntryKind,
         index: DefIndex,
         parent_did: DefId,
@@ -886,7 +886,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         )
     }
 
-    fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
+    fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
         let kind = self.kind(item_id);
         let did = self.local_def_id(item_id);
 
@@ -914,7 +914,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_explicit_predicates(
-        &self,
+        self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> ty::GenericPredicates<'tcx> {
@@ -922,7 +922,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_inferred_outlives(
-        &self,
+        self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
@@ -935,7 +935,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_super_predicates(
-        &self,
+        self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> ty::GenericPredicates<'tcx> {
@@ -943,7 +943,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_explicit_item_bounds(
-        &self,
+        self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
@@ -955,11 +955,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .unwrap_or_default()
     }
 
-    fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
+    fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics {
         self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess))
     }
 
-    fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+    fn get_type(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         self.root
             .tables
             .ty
@@ -968,63 +968,63 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, tcx))
     }
 
-    fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
+    fn get_stability(self, id: DefIndex) -> Option<attr::Stability> {
         self.root.tables.stability.get(self, id).map(|stab| stab.decode(self))
     }
 
-    fn get_const_stability(&self, id: DefIndex) -> Option<attr::ConstStability> {
+    fn get_const_stability(self, id: DefIndex) -> Option<attr::ConstStability> {
         self.root.tables.const_stability.get(self, id).map(|stab| stab.decode(self))
     }
 
-    fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
+    fn get_deprecation(self, id: DefIndex) -> Option<attr::Deprecation> {
         self.root.tables.deprecation.get(self, id).map(|depr| depr.decode(self))
     }
 
-    fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
+    fn get_visibility(self, id: DefIndex) -> ty::Visibility {
         self.root.tables.visibility.get(self, id).unwrap().decode(self)
     }
 
-    fn get_impl_data(&self, id: DefIndex) -> ImplData {
+    fn get_impl_data(self, id: DefIndex) -> ImplData {
         match self.kind(id) {
             EntryKind::Impl(data) => data.decode(self),
             _ => bug!(),
         }
     }
 
-    fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
+    fn get_parent_impl(self, id: DefIndex) -> Option<DefId> {
         self.get_impl_data(id).parent_impl
     }
 
-    fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
+    fn get_impl_polarity(self, id: DefIndex) -> ty::ImplPolarity {
         self.get_impl_data(id).polarity
     }
 
-    fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
+    fn get_impl_defaultness(self, id: DefIndex) -> hir::Defaultness {
         self.get_impl_data(id).defaultness
     }
 
-    fn get_impl_constness(&self, id: DefIndex) -> hir::Constness {
+    fn get_impl_constness(self, id: DefIndex) -> hir::Constness {
         self.get_impl_data(id).constness
     }
 
-    fn get_trait_item_def_id(&self, id: DefIndex) -> Option<DefId> {
+    fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
         self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode(self))
     }
 
-    fn get_coerce_unsized_info(&self, id: DefIndex) -> Option<ty::adjustment::CoerceUnsizedInfo> {
+    fn get_coerce_unsized_info(self, id: DefIndex) -> Option<ty::adjustment::CoerceUnsizedInfo> {
         self.get_impl_data(id).coerce_unsized_info
     }
 
-    fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
+    fn get_impl_trait(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
         self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
     }
 
-    fn get_expn_that_defined(&self, id: DefIndex, sess: &Session) -> ExpnId {
+    fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
         self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess))
     }
 
     fn get_const_param_default(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
     ) -> rustc_middle::ty::Const<'tcx> {
@@ -1032,14 +1032,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     /// Iterates over all the stability attributes in the given crate.
-    fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
+    fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
         // FIXME: For a proc macro crate, not sure whether we should return the "host"
         // features or an empty Vec. Both don't cause ICEs.
         tcx.arena.alloc_from_iter(self.root.lib_features.decode(self))
     }
 
     /// Iterates over the language items in the given crate.
-    fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
+    fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
         if self.root.is_proc_macro_crate() {
             // Proc macro crates do not export any lang-items to the target.
             &[]
@@ -1054,7 +1054,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     /// Iterates over the diagnostic items in the given crate.
-    fn get_diagnostic_items(&self) -> DiagnosticItems {
+    fn get_diagnostic_items(self) -> DiagnosticItems {
         if self.root.is_proc_macro_crate() {
             // Proc macro crates do not export any diagnostic-items to the target.
             Default::default()
@@ -1079,7 +1079,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     /// Module here is understood in name resolution sense - it can be a `mod` item,
     /// or a crate root, or an enum, or a trait.
     fn for_each_module_child(
-        &self,
+        self,
         id: DefIndex,
         mut callback: impl FnMut(ModChild),
         sess: &Session,
@@ -1177,15 +1177,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn is_ctfe_mir_available(&self, id: DefIndex) -> bool {
+    fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
         self.root.tables.mir_for_ctfe.get(self, id).is_some()
     }
 
-    fn is_item_mir_available(&self, id: DefIndex) -> bool {
+    fn is_item_mir_available(self, id: DefIndex) -> bool {
         self.root.tables.mir.get(self, id).is_some()
     }
 
-    fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
+    fn module_expansion(self, id: DefIndex, sess: &Session) -> ExpnId {
         match self.kind(id) {
             EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => {
                 self.get_expn_that_defined(id, sess)
@@ -1194,7 +1194,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
+    fn get_optimized_mir(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
         self.root
             .tables
             .mir
@@ -1205,7 +1205,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, tcx))
     }
 
-    fn get_mir_for_ctfe(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
+    fn get_mir_for_ctfe(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
         self.root
             .tables
             .mir_for_ctfe
@@ -1217,7 +1217,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_thir_abstract_const(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
     ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
@@ -1228,7 +1228,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
     }
 
-    fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> {
+    fn get_unused_generic_params(self, id: DefIndex) -> FiniteBitSet<u32> {
         self.root
             .tables
             .unused_generic_params
@@ -1237,7 +1237,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .unwrap_or_default()
     }
 
-    fn get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec<Promoted, Body<'tcx>> {
+    fn get_promoted_mir(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec<Promoted, Body<'tcx>> {
         self.root
             .tables
             .promoted_mir
@@ -1248,7 +1248,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, tcx))
     }
 
-    fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs {
+    fn mir_const_qualif(self, id: DefIndex) -> mir::ConstQualifs {
         match self.kind(id) {
             EntryKind::AnonConst(qualif, _)
             | EntryKind::Const(qualif, _)
@@ -1263,14 +1263,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_fn_has_self_parameter(&self, id: DefIndex) -> bool {
+    fn get_fn_has_self_parameter(self, id: DefIndex) -> bool {
         match self.kind(id) {
             EntryKind::AssocFn(data) => data.decode(self).has_self,
             _ => false,
         }
     }
 
-    fn get_associated_item_def_ids(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [DefId] {
+    fn get_associated_item_def_ids(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [DefId] {
         if let Some(children) = self.root.tables.children.get(self, id) {
             tcx.arena.alloc_from_iter(
                 children.decode((self, tcx.sess)).map(|child_index| self.local_def_id(child_index)),
@@ -1280,7 +1280,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_associated_item(&self, id: DefIndex, sess: &Session) -> ty::AssocItem {
+    fn get_associated_item(self, id: DefIndex, sess: &Session) -> ty::AssocItem {
         let def_key = self.def_key(id);
         let parent = self.local_def_id(def_key.parent.unwrap());
         let ident = self.item_ident(id, sess);
@@ -1307,11 +1307,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_item_variances(&'a self, id: DefIndex) -> impl Iterator<Item = ty::Variance> + 'a {
+    fn get_item_variances(self, id: DefIndex) -> impl Iterator<Item = ty::Variance> + 'a {
         self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self)
     }
 
-    fn get_ctor_def_id_and_kind(&self, node_id: DefIndex) -> Option<(DefId, CtorKind)> {
+    fn get_ctor_def_id_and_kind(self, node_id: DefIndex) -> Option<(DefId, CtorKind)> {
         match self.kind(node_id) {
             EntryKind::Struct(data, _) | EntryKind::Variant(data) => {
                 let vdata = data.decode(self);
@@ -1322,7 +1322,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_item_attrs(
-        &'a self,
+        self,
         id: DefIndex,
         sess: &'a Session,
     ) -> impl Iterator<Item = ast::Attribute> + 'a {
@@ -1346,7 +1346,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, sess))
     }
 
-    fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<Symbol>> {
+    fn get_struct_field_names(self, id: DefIndex, sess: &Session) -> Vec<Spanned<Symbol>> {
         self.root
             .tables
             .children
@@ -1357,7 +1357,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .collect()
     }
 
-    fn get_struct_field_visibilities(&self, id: DefIndex) -> Vec<Visibility> {
+    fn get_struct_field_visibilities(self, id: DefIndex) -> Vec<Visibility> {
         self.root
             .tables
             .children
@@ -1369,7 +1369,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_inherent_implementations_for_type(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
     ) -> &'tcx [DefId] {
@@ -1384,20 +1384,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         )
     }
 
-    fn get_traits(&'a self) -> impl Iterator<Item = DefId> + 'a {
-        self.root.traits.decode(self).map(|index| self.local_def_id(index))
+    fn get_traits(self) -> impl Iterator<Item = DefId> + 'a {
+        self.root.traits.decode(self).map(move |index| self.local_def_id(index))
     }
 
-    fn get_trait_impls(&'a self) -> impl Iterator<Item = (DefId, Option<SimplifiedType>)> + 'a {
-        self.trait_impls.values().flat_map(move |impls| {
+    fn get_trait_impls(self) -> impl Iterator<Item = (DefId, Option<SimplifiedType>)> + 'a {
+        self.cdata.trait_impls.values().flat_map(move |impls| {
             impls
                 .decode(self)
-                .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty))
+                .map(move |(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty))
         })
     }
 
     fn get_implementations_of_trait(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
         trait_def_id: DefId,
     ) -> &'tcx [(DefId, Option<SimplifiedType>)] {
@@ -1424,7 +1424,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
+    fn get_trait_of_item(self, id: DefIndex) -> Option<DefId> {
         let def_key = self.def_key(id);
         match def_key.disambiguated_data.data {
             DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
@@ -1437,7 +1437,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         })
     }
 
-    fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLib> {
+    fn get_native_libraries(self, sess: &Session) -> Vec<NativeLib> {
         if self.root.is_proc_macro_crate() {
             // Proc macro crates do not have any *target* native libraries.
             vec![]
@@ -1446,7 +1446,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_proc_macro_quoted_span(&self, index: usize, sess: &Session) -> Span {
+    fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span {
         self.root
             .tables
             .proc_macro_quoted_spans
@@ -1455,7 +1455,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, sess))
     }
 
-    fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> Lrc<FxHashMap<DefId, ForeignModule>> {
+    fn get_foreign_modules(self, tcx: TyCtxt<'tcx>) -> Lrc<FxHashMap<DefId, ForeignModule>> {
         if self.root.is_proc_macro_crate() {
             // Proc macro crates do not have any *target* foreign modules.
             Lrc::new(FxHashMap::default())
@@ -1467,7 +1467,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_dylib_dependency_formats(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx [(CrateNum, LinkagePreference)] {
         tcx.arena.alloc_from_iter(
@@ -1478,7 +1478,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         )
     }
 
-    fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
+    fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
         if self.root.is_proc_macro_crate() {
             // Proc macro crates do not depend on any target weak lang-items.
             &[]
@@ -1487,7 +1487,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] {
+    fn get_fn_param_names(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] {
         let param_names = match self.kind(id) {
             EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names,
             EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names,
@@ -1497,7 +1497,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn exported_symbols(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] {
         if self.root.is_proc_macro_crate() {
@@ -1509,7 +1509,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_rendered_const(&self, id: DefIndex) -> String {
+    fn get_rendered_const(self, id: DefIndex) -> String {
         match self.kind(id) {
             EntryKind::AnonConst(_, data)
             | EntryKind::Const(_, data)
@@ -1518,7 +1518,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_macro(&self, id: DefIndex, sess: &Session) -> MacroDef {
+    fn get_macro(self, id: DefIndex, sess: &Session) -> MacroDef {
         match self.kind(id) {
             EntryKind::MacroDef(macro_def) => macro_def.decode((self, sess)),
             _ => bug!(),
@@ -1527,7 +1527,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
     // This replicates some of the logic of the crate-local `is_const_fn_raw` query, because we
     // don't serialize constness for tuple variant and tuple struct constructors.
-    fn is_const_fn_raw(&self, id: DefIndex) -> bool {
+    fn is_const_fn_raw(self, id: DefIndex) -> bool {
         let constness = match self.kind(id) {
             EntryKind::AssocFn(data) => data.decode(self).fn_data.constness,
             EntryKind::Fn(data) => data.decode(self).constness,
@@ -1538,7 +1538,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         constness == hir::Constness::Const
     }
 
-    fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
+    fn asyncness(self, id: DefIndex) -> hir::IsAsync {
         match self.kind(id) {
             EntryKind::Fn(data) => data.decode(self).asyncness,
             EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness,
@@ -1547,7 +1547,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn is_foreign_item(&self, id: DefIndex) -> bool {
+    fn is_foreign_item(self, id: DefIndex) -> bool {
         match self.kind(id) {
             EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => {
                 true
@@ -1556,7 +1556,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn static_mutability(&self, id: DefIndex) -> Option<hir::Mutability> {
+    fn static_mutability(self, id: DefIndex) -> Option<hir::Mutability> {
         match self.kind(id) {
             EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Some(hir::Mutability::Not),
             EntryKind::MutStatic | EntryKind::ForeignMutStatic => Some(hir::Mutability::Mut),
@@ -1564,19 +1564,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn generator_kind(&self, id: DefIndex) -> Option<hir::GeneratorKind> {
+    fn generator_kind(self, id: DefIndex) -> Option<hir::GeneratorKind> {
         match self.kind(id) {
             EntryKind::Generator(data) => Some(data),
             _ => None,
         }
     }
 
-    fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
+    fn fn_sig(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
         self.root.tables.fn_sig.get(self, id).unwrap().decode((self, tcx))
     }
 
     #[inline]
-    fn def_key(&self, index: DefIndex) -> DefKey {
+    fn def_key(self, index: DefIndex) -> DefKey {
         *self
             .def_key_cache
             .lock()
@@ -1585,13 +1585,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     // Returns the path leading to the thing with this `id`.
-    fn def_path(&self, id: DefIndex) -> DefPath {
+    fn def_path(self, id: DefIndex) -> DefPath {
         debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
         DefPath::make(self.cnum, id, |parent| self.def_key(parent))
     }
 
     fn def_path_hash_unlocked(
-        &self,
+        self,
         index: DefIndex,
         def_path_hashes: &mut FxHashMap<DefIndex, DefPathHash>,
     ) -> DefPathHash {
@@ -1601,17 +1601,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     #[inline]
-    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+    fn def_path_hash(self, index: DefIndex) -> DefPathHash {
         let mut def_path_hashes = self.def_path_hash_cache.lock();
         self.def_path_hash_unlocked(index, &mut def_path_hashes)
     }
 
     #[inline]
-    fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex {
+    fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex {
         self.def_path_hash_map.def_path_hash_to_def_index(&hash)
     }
 
-    fn expn_hash_to_expn_id(&self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
+    fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId {
         debug_assert_eq!(ExpnId::from_hash(hash), None);
         let index_guess = ExpnIndex::from_u32(index_guess);
         let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
@@ -1669,7 +1669,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     ///
     /// Proc macro crates don't currently export spans, so this function does not have
     /// to work for them.
-    fn imported_source_files(&self, sess: &Session) -> &'a [ImportedSourceFile] {
+    fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] {
         // Translate the virtual `/rustc/$hash` prefix back to a real directory
         // that should hold actual sources, where possible.
         //
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1422537cd50..3a6c091b331 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -247,6 +247,9 @@ pub struct CodegenUnit<'tcx> {
     items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
     size_estimate: Option<usize>,
     primary: bool,
+    /// True if this is CGU is used to hold code coverage information for dead code,
+    /// false otherwise.
+    is_code_coverage_dead_code_cgu: bool,
 }
 
 /// Specifies the linkage type for a `MonoItem`.
@@ -277,7 +280,13 @@ pub enum Visibility {
 impl<'tcx> CodegenUnit<'tcx> {
     #[inline]
     pub fn new(name: Symbol) -> CodegenUnit<'tcx> {
-        CodegenUnit { name, items: Default::default(), size_estimate: None, primary: false }
+        CodegenUnit {
+            name,
+            items: Default::default(),
+            size_estimate: None,
+            primary: false,
+            is_code_coverage_dead_code_cgu: false,
+        }
     }
 
     pub fn name(&self) -> Symbol {
@@ -304,6 +313,15 @@ impl<'tcx> CodegenUnit<'tcx> {
         &mut self.items
     }
 
+    pub fn is_code_coverage_dead_code_cgu(&self) -> bool {
+        self.is_code_coverage_dead_code_cgu
+    }
+
+    /// Marks this CGU as the one used to contain code coverage information for dead code.
+    pub fn make_code_coverage_dead_code_cgu(&mut self) {
+        self.is_code_coverage_dead_code_cgu = true;
+    }
+
     pub fn mangle_name(human_readable_name: &str) -> String {
         // We generate a 80 bit hash from the name. This should be enough to
         // avoid collisions and is still reasonably short for filenames.
@@ -404,9 +422,11 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
             // The size estimate is not relevant to the hash
             size_estimate: _,
             primary: _,
+            is_code_coverage_dead_code_cgu,
         } = *self;
 
         name.hash_stable(hcx, hasher);
+        is_code_coverage_dead_code_cgu.hash_stable(hcx, hasher);
 
         let mut items: Vec<(Fingerprint, _)> = items
             .iter()
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6dd1ee893a4..3772f1c9fea 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -386,16 +386,6 @@ rustc_queries! {
         storage(ArenaCacheSelector<'tcx>)
     }
 
-    /// Returns the name of the file that contains the function body, if instrumented for coverage.
-    query covered_file_name(key: DefId) -> Option<Symbol> {
-        desc {
-            |tcx| "retrieving the covered file name, if instrumented, for `{}`",
-            tcx.def_path_str(key)
-        }
-        storage(ArenaCacheSelector<'tcx>)
-        cache_on_disk_if { key.is_local() }
-    }
-
     /// Returns the `CodeRegions` for a function that has instrumented coverage, in case the
     /// function was optimized out before codegen, and before being added to the Coverage Map.
     query covered_code_regions(key: DefId) -> Vec<&'tcx mir::coverage::CodeRegion> {
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index 1721fb5cde0..46de6d939a1 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -9,7 +9,6 @@ use rustc_span::def_id::DefId;
 /// A `query` provider for retrieving coverage information injected into MIR.
 pub(crate) fn provide(providers: &mut Providers) {
     providers.coverageinfo = |tcx, def_id| coverageinfo(tcx, def_id);
-    providers.covered_file_name = |tcx, def_id| covered_file_name(tcx, def_id);
     providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id);
 }
 
@@ -137,25 +136,6 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
     coverage_visitor.info
 }
 
-fn covered_file_name(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
-    if tcx.is_mir_available(def_id) {
-        let body = mir_body(tcx, def_id);
-        for bb_data in body.basic_blocks().iter() {
-            for statement in bb_data.statements.iter() {
-                if let StatementKind::Coverage(box ref coverage) = statement.kind {
-                    if let Some(code_region) = coverage.code_region.as_ref() {
-                        if is_inlined(body, statement) {
-                            continue;
-                        }
-                        return Some(code_region.file_name);
-                    }
-                }
-            }
-        }
-    }
-    return None;
-}
-
 fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> {
     let body = mir_body(tcx, def_id);
     body.basic_blocks()
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index dc22ffc6747..67597a0d7b4 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -201,6 +201,40 @@ pub fn partition<'tcx>(
         partitioner.internalize_symbols(cx, &mut post_inlining);
     }
 
+    let instrument_dead_code =
+        tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions();
+
+    if instrument_dead_code {
+        assert!(
+            post_inlining.codegen_units.len() > 0,
+            "There must be at least one CGU that code coverage data can be generated in."
+        );
+
+        // Find the smallest CGU that has exported symbols and put the dead
+        // function stubs in that CGU. We look for exported symbols to increase
+        // the likelihood the linker won't throw away the dead functions.
+        // FIXME(#92165): In order to truly resolve this, we need to make sure
+        // the object file (CGU) containing the dead function stubs is included
+        // in the final binary. This will probably require forcing these
+        // function symbols to be included via `-u` or `/include` linker args.
+        let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect();
+        cgus.sort_by_key(|cgu| cgu.size_estimate());
+
+        let dead_code_cgu = if let Some(cgu) = cgus
+            .into_iter()
+            .rev()
+            .filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External))
+            .next()
+        {
+            cgu
+        } else {
+            // If there are no CGUs that have externally linked items,
+            // then we just pick the first CGU as a fallback.
+            &mut post_inlining.codegen_units[0]
+        };
+        dead_code_cgu.make_code_coverage_dead_code_cgu();
+    }
+
     // Finally, sort by codegen unit name, so that we get deterministic results.
     let PostInliningPartitioning {
         codegen_units: mut result,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 12ca3faeb37..d662f61e2cf 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -4,7 +4,9 @@ use crate::infer::canonical::{
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::query::Fallible;
 use crate::traits::ObligationCause;
-use rustc_infer::infer::canonical::Canonical;
+use rustc_infer::infer::canonical::{Canonical, Certainty};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::PredicateObligations;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use std::fmt;
@@ -17,7 +19,6 @@ pub mod implied_outlives_bounds;
 pub mod normalize;
 pub mod outlives;
 pub mod prove_predicate;
-use self::prove_predicate::ProvePredicate;
 pub mod subtype;
 
 pub use rustc_middle::traits::query::type_op::*;
@@ -80,9 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
         query_key: ParamEnvAnd<'tcx, Self>,
         infcx: &InferCtxt<'_, 'tcx>,
         output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
-    ) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
+    ) -> Fallible<(
+        Self::QueryResponse,
+        Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
+        PredicateObligations<'tcx>,
+        Certainty,
+    )> {
         if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
-            return Ok((result, None));
+            return Ok((result, None, vec![], Certainty::Proven));
         }
 
         // FIXME(#33684) -- We need to use
@@ -104,20 +110,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
                 output_query_region_constraints,
             )?;
 
-        // Typically, instantiating NLL query results does not
-        // create obligations. However, in some cases there
-        // are unresolved type variables, and unify them *can*
-        // create obligations. In that case, we have to go
-        // fulfill them. We do this via a (recursive) query.
-        for obligation in obligations {
-            let ((), _) = ProvePredicate::fully_perform_into(
-                obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
-                infcx,
-                output_query_region_constraints,
-            )?;
-        }
-
-        Ok((value, Some(canonical_self)))
+        Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty))
     }
 }
 
@@ -129,9 +122,39 @@ where
 
     fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
         let mut region_constraints = QueryRegionConstraints::default();
-        let (output, canonicalized_query) =
+        let (output, canonicalized_query, mut obligations, _) =
             Q::fully_perform_into(self, infcx, &mut region_constraints)?;
 
+        // Typically, instantiating NLL query results does not
+        // create obligations. However, in some cases there
+        // are unresolved type variables, and unify them *can*
+        // create obligations. In that case, we have to go
+        // fulfill them. We do this via a (recursive) query.
+        while !obligations.is_empty() {
+            trace!("{:#?}", obligations);
+            let mut progress = false;
+            for obligation in std::mem::take(&mut obligations) {
+                let obligation = infcx.resolve_vars_if_possible(obligation);
+                match ProvePredicate::fully_perform_into(
+                    obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
+                    infcx,
+                    &mut region_constraints,
+                ) {
+                    Ok(((), _, new, certainty)) => {
+                        obligations.extend(new);
+                        progress = true;
+                        if let Certainty::Ambiguous = certainty {
+                            obligations.push(obligation);
+                        }
+                    }
+                    Err(_) => obligations.push(obligation),
+                }
+            }
+            if !progress {
+                return Err(NoSolution);
+            }
+        }
+
         // Promote the final query-region-constraints into a
         // (optional) ref-counted vector:
         let region_constraints =