From b1ce8a4ecdcdb179d023d9fd1061575ba651aeeb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Jan 2024 22:13:39 +0000 Subject: Move `check_mod_impl_wf` query call out of track_errors and bubble errors up instead. --- compiler/rustc_middle/src/query/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_middle/src') diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1dc77220881..6e5870df7c1 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -961,8 +961,9 @@ rustc_queries! { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } - query check_mod_impl_wf(key: LocalModDefId) -> () { + query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } + ensure_forwards_result_if_red } query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { -- cgit 1.4.1-3-g733a5 From 49347ee12dd23c357d45374a6e442e2c32fa4202 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 08:57:07 +0000 Subject: Make crate_inherent_impls_overlap_check bubble up its errors --- .../src/coherence/inherent_impls_overlap.rs | 46 +++++++++++++--------- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 3 +- 3 files changed, 31 insertions(+), 20 deletions(-) (limited to 'compiler/rustc_middle/src') diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 4c3455c7240..d66f073b1b4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -6,16 +6,18 @@ use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; use rustc_trait_selection::traits::{self, SkipLeakCheck}; use smallvec::SmallVec; use std::collections::hash_map::Entry; -pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) { +pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> { let mut inherent_overlap_checker = InherentOverlapChecker { tcx }; + let mut res = Ok(()); for id in tcx.hir().items() { - inherent_overlap_checker.check_item(id); + res = res.and(inherent_overlap_checker.check_item(id)); } + res } struct InherentOverlapChecker<'tcx> { @@ -58,10 +60,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { == item2.ident(self.tcx).normalize_to_macros_2_0() } - fn check_for_duplicate_items_in_impl(&self, impl_: DefId) { + fn check_for_duplicate_items_in_impl(&self, impl_: DefId) -> Result<(), ErrorGuaranteed> { let impl_items = self.tcx.associated_items(impl_); let mut seen_items = FxHashMap::default(); + let mut res = Ok(()); for impl_item in impl_items.in_definition_order() { let span = self.tcx.def_span(impl_item.def_id); let ident = impl_item.ident(self.tcx); @@ -70,7 +73,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { match seen_items.entry(norm_ident) { Entry::Occupied(entry) => { let former = entry.get(); - struct_span_code_err!( + res = Err(struct_span_code_err!( self.tcx.dcx(), span, E0592, @@ -79,13 +82,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ) .with_span_label(span, format!("duplicate definitions for `{ident}`")) .with_span_label(*former, format!("other definition for `{ident}`")) - .emit(); + .emit()); } Entry::Vacant(entry) => { entry.insert(span); } } } + res } fn check_for_common_items_in_impls( @@ -93,10 +97,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl1: DefId, impl2: DefId, overlap: traits::OverlapResult<'_>, - ) { + ) -> Result<(), ErrorGuaranteed> { let impl_items1 = self.tcx.associated_items(impl1); let impl_items2 = self.tcx.associated_items(impl2); + let mut res = Ok(()); for &item1 in impl_items1.in_definition_order() { let collision = impl_items2 .filter_by_name_unhygienic(item1.name) @@ -128,9 +133,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> { traits::add_placeholder_note(&mut err); } - err.emit(); + res = Err(err.emit()); } } + res } fn check_for_overlapping_inherent_impls( @@ -138,7 +144,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { overlap_mode: OverlapMode, impl1_def_id: DefId, impl2_def_id: DefId, - ) { + ) -> Result<(), ErrorGuaranteed> { let maybe_overlap = traits::overlapping_impls( self.tcx, impl1_def_id, @@ -150,14 +156,16 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ); if let Some(overlap) = maybe_overlap { - self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap); + self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap) + } else { + Ok(()) } } - fn check_item(&mut self, id: hir::ItemId) { + fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> { let def_kind = self.tcx.def_kind(id.owner_id); if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) { - return; + return Ok(()); } let impls = self.tcx.inherent_impls(id.owner_id); @@ -173,17 +181,18 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // otherwise switch to an allocating algorithm with // faster asymptotic runtime. const ALLOCATING_ALGO_THRESHOLD: usize = 500; + let mut res = Ok(()); if impls.len() < ALLOCATING_ALGO_THRESHOLD { for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { - self.check_for_duplicate_items_in_impl(impl1_def_id); + res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( + res = res.and(self.check_for_overlapping_inherent_impls( overlap_mode, impl1_def_id, impl2_def_id, - ); + )); } } } @@ -315,20 +324,21 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl_blocks.sort_unstable(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; - self.check_for_duplicate_items_in_impl(impl1_def_id); + res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( + res = res.and(self.check_for_overlapping_inherent_impls( overlap_mode, impl1_def_id, impl2_def_id, - ); + )); } } } } } + res } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1a370ad10cf..da9a97db9a4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -184,8 +184,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // these queries are executed for side-effects (error reporting): tcx.ensure().crate_inherent_impls(()); - tcx.ensure().crate_inherent_impls_overlap_check(()); })) + .and(tcx.ensure().crate_inherent_impls_overlap_check(())) })?; if tcx.features().rustc_attrs { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6e5870df7c1..15f0dc0208d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1019,8 +1019,9 @@ rustc_queries! { /// Checks all types in the crate for overlap in their inherent impls. Reports errors. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls_overlap_check(_: ()) -> () { + query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for overlap between inherent impls defined in this crate" } + ensure_forwards_result_if_red } /// Checks whether all impls in the crate pass the overlap check, returning -- cgit 1.4.1-3-g733a5 From 557b11187090b0ec749b07858c6ac18f95b7490e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 14:29:54 +0000 Subject: Make crate_inherent_impls fallible and stop using `track_errors` for it --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../src/coherence/inherent_impls.rs | 79 +++++++++++++--------- .../src/coherence/inherent_impls_overlap.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 5 +- compiler/rustc_hir_typeck/src/expr.rs | 3 +- compiler/rustc_hir_typeck/src/method/probe.rs | 6 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 19 ++++-- .../src/rmeta/decoder/cstore_impl.rs | 4 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/query/erase.rs | 4 ++ compiler/rustc_middle/src/query/mod.rs | 10 +-- compiler/rustc_middle/src/query/plumbing.rs | 12 ++-- compiler/rustc_middle/src/ty/trait_def.rs | 18 ++++- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 6 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/types.rs | 4 +- src/librustdoc/passes/collect_intra_doc_links.rs | 3 +- 19 files changed, 115 insertions(+), 73 deletions(-) (limited to 'compiler/rustc_middle/src') diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9f4f1413650..b9e72a3b1ea 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1446,7 +1446,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let candidates: Vec<_> = tcx - .inherent_impls(adt_did) + .inherent_impls(adt_did)? .iter() .filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?))) .collect(); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 3162004a634..abef365c3ca 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -13,32 +13,41 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; /// On-demand query: yields a map containing all types mapped to their inherent impls. -pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { +pub fn crate_inherent_impls( + tcx: TyCtxt<'_>, + (): (), +) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> { let mut collect = InherentCollect { tcx, impls_map: Default::default() }; + let mut res = Ok(()); for id in tcx.hir().items() { - collect.check_item(id); + res = res.and(collect.check_item(id)); } - collect.impls_map + res?; + Ok(tcx.arena.alloc(collect.impls_map)) } -pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { - let crate_map = tcx.crate_inherent_impls(()); - tcx.arena.alloc_from_iter( +pub fn crate_incoherent_impls( + tcx: TyCtxt<'_>, + simp: SimplifiedType, +) -> Result<&[DefId], ErrorGuaranteed> { + let crate_map = tcx.crate_inherent_impls(())?; + Ok(tcx.arena.alloc_from_iter( crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()), - ) + )) } /// On-demand query: yields a vector of the inherent impls for a specific type. -pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] { - let crate_map = tcx.crate_inherent_impls(()); - match crate_map.inherent_impls.get(&ty_def_id) { +pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> { + let crate_map = tcx.crate_inherent_impls(())?; + Ok(match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], None => &[], - } + }) } struct InherentCollect<'tcx> { @@ -47,14 +56,19 @@ struct InherentCollect<'tcx> { } impl<'tcx> InherentCollect<'tcx> { - fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) { + fn check_def_id( + &mut self, + impl_def_id: LocalDefId, + self_ty: Ty<'tcx>, + ty_def_id: DefId, + ) -> Result<(), ErrorGuaranteed> { if let Some(ty_def_id) = ty_def_id.as_local() { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default(); vec.push(impl_def_id.to_def_id()); - return; + return Ok(()); } if self.tcx.features().rustc_attrs { @@ -62,18 +76,16 @@ impl<'tcx> InherentCollect<'tcx> { if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span }); - return; + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span })); } for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { span: impl_span, help_span: self.tcx.def_span(impl_item), - }); - return; + })); } } @@ -82,24 +94,28 @@ impl<'tcx> InherentCollect<'tcx> { } else { bug!("unexpected self type: {:?}", self_ty); } + Ok(()) } else { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }); + Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span })) } } - fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) { + fn check_primitive_impl( + &mut self, + impl_def_id: LocalDefId, + ty: Ty<'tcx>, + ) -> Result<(), ErrorGuaranteed> { let items = self.tcx.associated_item_def_ids(impl_def_id); if !self.tcx.hir().rustc_coherence_is_core() { if self.tcx.features().rustc_attrs { for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { span, help_span: self.tcx.def_span(impl_item), - }); - return; + })); } } } else { @@ -108,8 +124,7 @@ impl<'tcx> InherentCollect<'tcx> { if let ty::Ref(_, subty, _) = ty.kind() { note = Some(errors::InherentPrimitiveTyNote { subty: *subty }); } - self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note }); - return; + return Err(self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note })); } } @@ -118,11 +133,12 @@ impl<'tcx> InherentCollect<'tcx> { } else { bug!("unexpected primitive type: {:?}", ty); } + Ok(()) } - fn check_item(&mut self, id: hir::ItemId) { + fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> { if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) { - return; + return Ok(()); } let id = id.owner_id.def_id; @@ -132,10 +148,10 @@ impl<'tcx> InherentCollect<'tcx> { ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()), ty::Foreign(did) => self.check_def_id(id, self_ty, did), ty::Dynamic(data, ..) if data.principal_def_id().is_some() => { - self.check_def_id(id, self_ty, data.principal_def_id().unwrap()); + self.check_def_id(id, self_ty, data.principal_def_id().unwrap()) } ty::Dynamic(..) => { - self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }); + Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span })) } ty::Bool | ty::Char @@ -151,7 +167,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::FnPtr(_) | ty::Tuple(..) => self.check_primitive_impl(id, self_ty), ty::Alias(..) | ty::Param(_) => { - self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }); + Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span })) } ty::FnDef(..) | ty::Closure(..) @@ -162,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Infer(_) => { bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty); } - ty::Error(_) => {} + // We could bail out here, but that will silence other useful errors. + ty::Error(_) => Ok(()), } } } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index d66f073b1b4..63ea0272014 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -168,7 +168,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { return Ok(()); } - let impls = self.tcx.inherent_impls(id.owner_id); + let impls = self.tcx.inherent_impls(id.owner_id)?; let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id()); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index da9a97db9a4..08956d222d2 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -181,10 +181,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { for &trait_def_id in tcx.all_local_trait_impls(()).keys() { tcx.ensure().coherent_trait(trait_def_id); } - - // these queries are executed for side-effects (error reporting): - tcx.ensure().crate_inherent_impls(()); })) + // these queries are executed for side-effects (error reporting): + .and(tcx.ensure().crate_inherent_impls(())) .and(tcx.ensure().crate_inherent_impls_overlap_check(())) })?; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ac8701a33d4..065052d9a5d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2104,7 +2104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut items = self .tcx .inherent_impls(def_id) - .iter() + .into_iter() + .flatten() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. .filter(|item| { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 10c31d8c641..4dc802008d0 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -711,14 +711,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else { bug!("unexpected incoherent type: {:?}", self_ty) }; - for &impl_def_id in self.tcx.incoherent_impls(simp) { + for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() { self.assemble_inherent_impl_probe(impl_def_id); } } fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) { - let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id); - for &impl_def_id in impl_def_ids.iter() { + let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten(); + for &impl_def_id in impl_def_ids { self.assemble_inherent_impl_probe(impl_def_id); } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3bf1e1312b3..0b8a25eedaf 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -359,7 +359,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(adt_def, _) = ty.kind() { self.tcx .inherent_impls(adt_def.did()) - .iter() + .into_iter() + .flatten() .any(|def_id| self.associated_value(*def_id, item_name).is_some()) } else { false @@ -1048,7 +1049,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut inherent_impls_candidate = self .tcx .inherent_impls(adt.did()) - .iter() + .into_iter() + .flatten() .copied() .filter(|def_id| { if let Some(assoc) = self.associated_value(*def_id, item_name) { @@ -1103,7 +1105,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the {item_kind} was found for\n{type_candidates}{additional_types}" )); } else { - 'outer: for inherent_impl_did in self.tcx.inherent_impls(adt.did()) { + 'outer: for inherent_impl_did in + self.tcx.inherent_impls(adt.did()).into_iter().flatten() + { for inherent_method in self.tcx.associated_items(inherent_impl_did).in_definition_order() { @@ -1457,9 +1461,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Adt(adt_def, _) = rcvr_ty.kind() else { return; }; - let mut items = self - .tcx - .inherent_impls(adt_def.did()) + // FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case. + let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return }; + let mut items = impls .iter() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. @@ -1823,7 +1827,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { simplify_type(tcx, ty, TreatParams::AsCandidateKey) .and_then(|simp| { tcx.incoherent_impls(simp) - .iter() + .into_iter() + .flatten() .find_map(|&id| self.associated_value(id, item_name)) }) .is_some() diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 912c2f36eb3..c3d6c21c402 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -283,7 +283,7 @@ provide! { tcx, def_id, other, cdata, tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index)) } associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) } - inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } + inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) } item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } @@ -328,7 +328,7 @@ provide! { tcx, def_id, other, cdata, traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) } trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) } implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } - crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) } + crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) } dep_kind => { cdata.dep_kind } module_children => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a458b528a97..2d4e49e27d9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1485,7 +1485,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } let inherent_impls = tcx.with_stable_hashing_context(|hcx| { - tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true) + tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true) }); for (def_id, impls) in inherent_impls { record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| { @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { empty_proc_macro!(self); let tcx = self.tcx; let all_impls = tcx.with_stable_hashing_context(|hcx| { - tcx.crate_inherent_impls(()).incoherent_impls.to_sorted(&hcx, true) + tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true) }); let all_impls: Vec<_> = all_impls diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 8a4fd01437f..e745913fabc 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -114,6 +114,7 @@ macro_rules! arena_types { [] mod_child: rustc_middle::metadata::ModChild, [] features: rustc_feature::Features, [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph, + [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, ]); ) } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b9200f1abf1..a49825bdd70 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -78,6 +78,10 @@ impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::>()]; } +impl EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Result<&'_ T, traits::CodegenObligationError> { type Result = [u8; size_of::>()]; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 15f0dc0208d..b3aa02e1aa3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -859,13 +859,13 @@ rustc_queries! { /// Maps a `DefId` of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. - query inherent_impls(key: DefId) -> &'tcx [DefId] { + query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } - query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { + query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting all inherent impls for `{:?}`", key } } @@ -1012,9 +1012,9 @@ rustc_queries! { /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls { - arena_cache + query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> { desc { "finding all inherent impls defined in crate" } + ensure_forwards_result_if_red } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. @@ -1647,7 +1647,7 @@ rustc_queries! { /// /// Do not call this directly, but instead use the `incoherent_impls` query. /// This query is only used to get the data necessary for that query. - query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { + query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting all impls for a type in a crate" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index a41d4f1ad58..8d88488e167 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -174,7 +174,7 @@ pub fn query_ensure<'tcx, Cache>( } #[inline] -pub fn query_ensure_error_guaranteed<'tcx, Cache>( +pub fn query_ensure_error_guaranteed<'tcx, Cache, T>( tcx: TyCtxt<'tcx>, execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option, query_cache: &Cache, @@ -182,14 +182,16 @@ pub fn query_ensure_error_guaranteed<'tcx, Cache>( check_cache: bool, ) -> Result<(), ErrorGuaranteed> where - Cache: QueryCache>>, + Cache: QueryCache>>, + Result: EraseType, { let key = key.into_query_param(); if let Some(res) = try_get_cached(tcx, query_cache, &key) { - super::erase::restore(res) + super::erase::restore(res).map(drop) } else { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }) .map(super::erase::restore) + .map(|res| res.map(drop)) // Either we actually executed the query, which means we got a full `Result`, // or we can just assume the query succeeded, because it was green in the // incremental cache. If it is green, that means that the previous compilation @@ -205,7 +207,7 @@ macro_rules! query_ensure { query_ensure($($args)*) }; ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => { - query_ensure_error_guaranteed($($args)*) + query_ensure_error_guaranteed($($args)*).map(|_| ()) }; ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { query_ensure!([$($modifiers)*]$($args)*) @@ -667,5 +669,7 @@ mod sealed { pub use sealed::IntoQueryParam; +use super::erase::EraseType; + #[derive(Copy, Clone, Debug, HashStable)] pub struct CyclePlaceholder(pub ErrorGuaranteed); diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 227a0753d04..d85b541d363 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -254,16 +254,28 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait } /// Query provider for `incoherent_impls`. -pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { +pub(super) fn incoherent_impls_provider( + tcx: TyCtxt<'_>, + simp: SimplifiedType, +) -> Result<&[DefId], ErrorGuaranteed> { let mut impls = Vec::new(); + let mut res = Ok(()); for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { - for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) { + let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) { + Ok(impls) => impls, + Err(e) => { + res = Err(e); + continue; + } + }; + for &impl_def_id in incoherent_impls { impls.push(impl_def_id) } } debug!(?impls); + res?; - tcx.arena.alloc_slice(&impls) + Ok(tcx.arena.alloc_slice(&impls)) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 070580860c1..20e70f87b75 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1433,7 +1433,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt } fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option { - for impl_def_id in tcx.inherent_impls(def_id) { + for impl_def_id in tcx.inherent_impls(def_id).ok()? { if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind( tcx, fn_ident, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 58ff4d8c793..5a95f2083f6 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1745,12 +1745,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // Doing analysis on local `DefId`s would cause infinite recursion. return; } + let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return }; // Look at all the associated functions without receivers in the type's // inherent impls to look for builders that return `Self` - let mut items = self - .r - .tcx - .inherent_impls(def_id) + let mut items = impls .iter() .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 014bcb1a881..aab974ad79e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -312,7 +312,7 @@ pub(crate) fn build_impls( let tcx = cx.tcx; // for each implementation of an item represented by `did`, build the clean::Item for that impl - for &did in tcx.inherent_impls(did).iter() { + for &did in tcx.inherent_impls(did).into_iter().flatten() { build_impl(cx, did, attrs, ret); } @@ -325,7 +325,7 @@ pub(crate) fn build_impls( if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; - for &did in tcx.incoherent_impls(type_) { + for &did in tcx.incoherent_impls(type_).into_iter().flatten() { build_impl(cx, did, attrs, ret); } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 90eb783c7ca..6710193f961 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1862,7 +1862,7 @@ impl PrimitiveType { .get(self) .into_iter() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten()) .copied() } @@ -1870,7 +1870,7 @@ impl PrimitiveType { Self::simplified_types() .values() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten()) .copied() } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index dbff33dc1ec..30b3e5c784d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -624,7 +624,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Checks if item_name belongs to `impl SomeItem` let mut assoc_items: Vec<_> = tcx .inherent_impls(did) - .iter() + .into_iter() + .flatten() .flat_map(|&imp| { filter_assoc_items_by_name_and_namespace( tcx, -- cgit 1.4.1-3-g733a5 From 8507f5105bb5294d802c38918b0b21916b376c16 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Thu, 11 Jan 2024 01:36:05 +0700 Subject: Improved collapse_debuginfo attribute, added command-line flag (no|external|yes) --- compiler/rustc_expand/messages.ftl | 3 ++ compiler/rustc_expand/src/base.rs | 56 ++++++++++++++++++++- compiler/rustc_expand/src/errors.rs | 7 +++ compiler/rustc_expand/src/mbe/macro_rules.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_interface/src/tests.rs | 9 ++-- compiler/rustc_metadata/src/rmeta/decoder.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_session/src/config.rs | 32 +++++++++--- compiler/rustc_session/src/options.rs | 17 +++++++ compiler/rustc_span/src/hygiene.rs | 19 ++++++-- compiler/rustc_span/src/symbol.rs | 2 + .../debuginfo/collapse-debuginfo-external-attr.rs | 31 ++++++++++++ ...se-debuginfo-external-flag-overriden-by-attr.rs | 34 +++++++++++++ .../debuginfo/collapse-debuginfo-external-flag.rs | 26 ++++++++++ tests/debuginfo/collapse-debuginfo-no-attr.rs | 2 +- .../debuginfo/collapse-debuginfo-with-yes-flag.rs | 57 ++++++++++++++++++++++ 17 files changed, 281 insertions(+), 21 deletions(-) create mode 100644 tests/debuginfo/collapse-debuginfo-external-attr.rs create mode 100644 tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs create mode 100644 tests/debuginfo/collapse-debuginfo-external-flag.rs create mode 100644 tests/debuginfo/collapse-debuginfo-with-yes-flag.rs (limited to 'compiler/rustc_middle/src') diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 475dd348e7b..3e3b4814300 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -16,6 +16,9 @@ expand_attributes_wrong_form = expand_cannot_be_name_of_macro = `{$trait_ident}` cannot be a name of {$macro_type} macro +expand_collapse_debuginfo_illegal = + illegal value for attribute #[collapse_debuginfo(no|external|yes)] + expand_count_repetition_misplaced = `count` can not be placed inside the inner-most repetition diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0a1c4430397..edc9c5a9130 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] +use crate::base::ast::NestedMetaItem; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; @@ -19,6 +20,7 @@ use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools}; use rustc_parse::{parser, MACRO_ARGUMENTS}; +use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; @@ -761,6 +763,55 @@ impl SyntaxExtension { } } + fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo { + use crate::errors::CollapseMacroDebuginfoIllegal; + // #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)]) + // considered as `yes` + attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| { + let [NestedMetaItem::MetaItem(item)] = &l[..] else { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span }); + return CollapseMacroDebuginfo::Unspecified; + }; + if !item.is_word() { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span }); + CollapseMacroDebuginfo::Unspecified + } else { + match item.name_or_empty() { + sym::no => CollapseMacroDebuginfo::No, + sym::external => CollapseMacroDebuginfo::External, + sym::yes => CollapseMacroDebuginfo::Yes, + _ => { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span }); + CollapseMacroDebuginfo::Unspecified + } + } + } + }) + } + + /// if-ext - if macro from different crate (related to callsite code) + /// | cmd \ attr | no | (unspecified) | external | yes | + /// | no | no | no | no | no | + /// | (unspecified) | no | no | if-ext | yes | + /// | external | no | if-ext | if-ext | yes | + /// | yes | yes | yes | yes | yes | + fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool { + let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo) + .map(|v| Self::collapse_debuginfo_by_name(sess, v)) + .unwrap_or(CollapseMacroDebuginfo::Unspecified); + let flag = sess.opts.unstable_opts.collapse_macro_debuginfo; + let attr = collapse_debuginfo_attr; + let ext = !is_local; + #[rustfmt::skip] + let collapse_table = [ + [false, false, false, false], + [false, false, ext, true], + [false, ext, ext, true], + [true, true, true, true], + ]; + collapse_table[flag as usize][attr as usize] + } + /// Constructs a syntax extension with the given properties /// and other properties converted from attributes. pub fn new( @@ -772,6 +823,7 @@ impl SyntaxExtension { edition: Edition, name: Symbol, attrs: &[ast::Attribute], + is_local: bool, ) -> SyntaxExtension { let allow_internal_unstable = attr::allow_internal_unstable(sess, attrs).collect::>(); @@ -780,8 +832,8 @@ impl SyntaxExtension { let local_inner_macros = attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros)); - let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo); - tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); + let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local); + tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro) .map(|attr| { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 2b43fae6852..4a1c00f0104 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -58,6 +58,13 @@ pub(crate) struct ResolveRelativePath { pub path: String, } +#[derive(Diagnostic)] +#[diag(expand_collapse_debuginfo_illegal)] +pub(crate) struct CollapseMacroDebuginfoIllegal { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(expand_macro_const_stability)] pub(crate) struct MacroConstStability { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 363b52aef8a..1a39708ed8e 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -367,6 +367,7 @@ pub fn compile_declarative_macro( edition, def.ident.name, &def.attrs, + def.id != DUMMY_NODE_ID, ) }; let dummy_syn_ext = || (mk_syn_ext(Box::new(macro_rules_dummy_expander)), Vec::new()); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4442b67df6e..68b6f69854d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -469,7 +469,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // `#[collapse_debuginfo]` gated!( - collapse_debuginfo, Normal, template!(Word), WarnFollowing, + collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing, experimental!(collapse_debuginfo) ), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 588139a303c..555c822ad6d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,10 +4,10 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, - FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, - LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, - Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + CollapseMacroDebuginfo, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, + ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, + InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, + OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; @@ -742,6 +742,7 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); + tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 49e849964be..20e3ae3ba94 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1027,6 +1027,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.edition, Symbol::intern(name), &attrs, + false, ) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ad9296a4cc8..a5d9e0fcf44 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2535,8 +2535,7 @@ impl<'tcx> TyCtxt<'tcx> { if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() { return span; } - let collapse_debuginfo_enabled = self.features().collapse_debuginfo; - hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled) + hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo) } #[inline] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ac15c3b407b..e751ff13a34 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3190,12 +3190,12 @@ pub enum WasiExecModel { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, - LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, - OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, - SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - WasiExecModel, + BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo, + DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold, + InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, + NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, + RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3274,6 +3274,7 @@ pub(crate) mod dep_tracking { LtoCli, DebugInfo, DebugInfoCompression, + CollapseMacroDebuginfo, UnstableFeatures, NativeLib, SanitizerSet, @@ -3437,6 +3438,25 @@ pub enum ProcMacroExecutionStrategy { CrossThread, } +/// How to perform collapse macros debug info +/// if-ext - if macro from different crate (related to callsite code) +/// | cmd \ attr | no | (unspecified) | external | yes | +/// | no | no | no | no | no | +/// | (unspecified) | no | no | if-ext | yes | +/// | external | no | if-ext | if-ext | yes | +/// | yes | yes | yes | yes | yes | +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum CollapseMacroDebuginfo { + /// Don't collapse debuginfo for the macro + No = 0, + /// Unspecified value + Unspecified = 1, + /// Collapse debuginfo if the macro comes from a different crate + External = 2, + /// Collapse debuginfo for the macro + Yes = 3, +} + /// Which format to use for `-Z dump-mono-stats` #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum DumpMonoStatsFormat { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f4bf79f93f2..6c91929fcbe 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -388,6 +388,7 @@ mod desc { pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; + pub const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -1302,6 +1303,19 @@ mod parse { true } + pub(crate) fn parse_collapse_macro_debuginfo( + slot: &mut CollapseMacroDebuginfo, + v: Option<&str>, + ) -> bool { + *slot = match v { + Some("no") => CollapseMacroDebuginfo::No, + Some("external") => CollapseMacroDebuginfo::External, + Some("yes") => CollapseMacroDebuginfo::Yes, + _ => return false, + }; + true + } + pub(crate) fn parse_proc_macro_execution_strategy( slot: &mut ProcMacroExecutionStrategy, v: Option<&str>, @@ -1534,6 +1548,9 @@ options! { "instrument control-flow architecture protection"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), + collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified, + parse_collapse_macro_debuginfo, [TRACKED], + "set option to collapse debuginfo for macros"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index d03965b539c..21623fdc1d2 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -464,12 +464,15 @@ impl HygieneData { &self, mut span: Span, to: Span, - collapse_debuginfo_enabled: bool, + collapse_debuginfo_feature_enabled: bool, ) -> Span { let orig_span = span; let mut ret_span = span; - debug!("walk_chain_collapsed({:?}, {:?})", span, to); + debug!( + "walk_chain_collapsed({:?}, {:?}), feature_enable={}", + span, to, collapse_debuginfo_feature_enabled, + ); debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt()); while !span.eq_ctxt(to) && span.from_expansion() { let outer_expn = self.outer_expn(span.ctxt()); @@ -477,7 +480,7 @@ impl HygieneData { let expn_data = self.expn_data(outer_expn); debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data); span = expn_data.call_site; - if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo { + if !collapse_debuginfo_feature_enabled || expn_data.collapse_debuginfo { ret_span = span; } } @@ -601,8 +604,14 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { HygieneData::with(|data| data.walk_chain(span, to)) } -pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span { - HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled)) +pub fn walk_chain_collapsed( + span: Span, + to: Span, + collapse_debuginfo_feature_enabled: bool, +) -> Span { + HygieneData::with(|hdata| { + hdata.walk_chain_collapsed(span, to, collapse_debuginfo_feature_enabled) + }) } pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 72b62a795fc..44795022cba 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -749,6 +749,7 @@ symbols! { extern_in_paths, extern_prelude, extern_types, + external, external_doc, f, f16c_target_feature, @@ -1811,6 +1812,7 @@ symbols! { xmm_reg, yeet_desugar_details, yeet_expr, + yes, yield_expr, ymm_reg, zmm_reg, diff --git a/tests/debuginfo/collapse-debuginfo-external-attr.rs b/tests/debuginfo/collapse-debuginfo-external-attr.rs new file mode 100644 index 00000000000..f36b0833ad5 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-attr.rs @@ -0,0 +1,31 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that local macro debug info is not collapsed with #[collapse_debuginfo(external)] + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#one_callsite[...] +// gdb-command:continue + +fn one() { + println!("one"); +} + +#[collapse_debuginfo(external)] +macro_rules! outer { + () => { + one(); // #one_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs b/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs new file mode 100644 index 00000000000..e5cbc1a685d --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs @@ -0,0 +1,34 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that macro attribute #[collapse_debuginfo(no)] +// overrides "collapse_macro_debuginfo=external" flag + +// compile-flags:-g -Z collapse_macro_debuginfo=external + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#one_callsite[...] +// gdb-command:next +// gdb-command:frame +// gdb-command:continue + +fn one() { + println!("one"); +} + +#[collapse_debuginfo(no)] +macro_rules! outer { + () => { + one(); // #one_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-external-flag.rs b/tests/debuginfo/collapse-debuginfo-external-flag.rs new file mode 100644 index 00000000000..9a0aef38ea6 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-flag.rs @@ -0,0 +1,26 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that println macro debug info is collapsed with "collapse_macro_debuginfo=external" flag + +// compile-flags:-g -Z collapse_macro_debuginfo=external + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#println_callsite[...] +// gdb-command:continue + +macro_rules! outer { + () => { + println!("one"); // #println_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-no-attr.rs b/tests/debuginfo/collapse-debuginfo-no-attr.rs index 230c8795be3..d156c381a15 100644 --- a/tests/debuginfo/collapse-debuginfo-no-attr.rs +++ b/tests/debuginfo/collapse-debuginfo-no-attr.rs @@ -4,7 +4,7 @@ // Test that line numbers are not replaced with those of the outermost expansion site when the // `collapse_debuginfo` feature is active and the attribute is not provided. -// compile-flags:-g +// compile-flags:-g -Z collapse_macro_debuginfo=no // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs b/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs new file mode 100644 index 00000000000..76a97a325d7 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs @@ -0,0 +1,57 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that line numbers are replaced with those of the outermost expansion site when the +// `collapse_debuginfo` feature is active and the command line flag is provided. + +// compile-flags:-g -Z collapse_macro_debuginfo=yes + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc1[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc2[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc3[...] +// gdb-command:continue + +fn one() { + println!("one"); +} +fn two() { + println!("two"); +} +fn three() { + println!("three"); +} +fn four() { + println!("four"); +} + +macro_rules! outer { + ($b:block) => { + one(); + inner!(); + $b + }; +} + +macro_rules! inner { + () => { + two(); + }; +} + +fn main() { + let ret = 0; // #break + outer!({ // #loc1 + three(); // #loc2 + four(); // #loc3 + }); + std::process::exit(ret); +} -- cgit 1.4.1-3-g733a5 From c13c746b477cfa3887bd88236c452bb57048f6c6 Mon Sep 17 00:00:00 2001 From: James Dietz Date: Thu, 18 Jan 2024 09:39:38 -0500 Subject: change unwrap to `?` on write where result is returned --- compiler/rustc_middle/src/mir/pretty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_middle/src') diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 239929a2c0e..f74715468a0 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1116,10 +1116,10 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> | ProjectionElem::Subtype(_) | ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { - write!(fmt, "(").unwrap(); + write!(fmt, "(")?; } ProjectionElem::Deref => { - write!(fmt, "(*").unwrap(); + write!(fmt, "(*")?; } ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } -- cgit 1.4.1-3-g733a5