diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 120 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/Cargo.toml | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/opaque_types.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder.rs | 196 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/mono.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/coverage/query.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/partitioning/mod.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs | 61 |
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 = |
