diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index f642902320d..a680730d1f5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -30,7 +30,6 @@ use rustc_session::cstore::{ }; use rustc_session::Session; use rustc_span::hygiene::ExpnIndex; -use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; @@ -1134,20 +1133,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_struct_field_names( - self, - id: DefIndex, - sess: &'a Session, - ) -> impl Iterator> + 'a { - self.root - .tables - .children - .get(self, id) - .expect("fields not encoded for a struct") - .decode(self) - .map(move |index| respan(self.get_span(index, sess), self.item_name(index))) - } - fn get_inherent_implementations_for_type( self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7e08ab0448c..7ace335dd3d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -19,8 +19,8 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::cstore::{CrateSource, CrateStore}; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; -use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, Symbol}; +use rustc_span::Span; use rustc_data_structures::sync::Lrc; use std::any::Any; @@ -507,14 +507,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { } impl CStore { - pub fn struct_field_names_untracked<'a>( - &'a self, - def: DefId, - sess: &'a Session, - ) -> impl Iterator> + 'a { - self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) - } - pub fn ctor_untracked(&self, def: DefId) -> Option<(CtorKind, DefId)> { self.get_crate_data(def.krate).get_ctor(def.index) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 415942405ae..362ef693c48 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -29,7 +29,6 @@ use rustc_middle::metadata::ModChild; use rustc_middle::{bug, ty}; use rustc_session::cstore::CrateStore; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; -use rustc_span::source_map::respan; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -327,13 +326,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn insert_field_names_local(&mut self, def_id: DefId, vdata: &ast::VariantData) { - let field_names = vdata - .fields() - .iter() - .map(|field| respan(field.span, field.ident.map_or(kw::Empty, |ident| ident.name))) - .collect(); - self.r.field_names.insert(def_id, field_names); + fn insert_field_def_ids(&mut self, def_id: LocalDefId, vdata: &ast::VariantData) { + if vdata.fields().iter().any(|field| field.is_placeholder) { + // The fields are not expanded yet. + return; + } + let def_ids = vdata.fields().iter().map(|field| self.r.local_def_id(field.id).to_def_id()); + self.r.field_def_ids.insert(def_id, self.r.tcx.arena.alloc_from_iter(def_ids)); } fn insert_field_visibilities_local(&mut self, def_id: DefId, vdata: &ast::VariantData) { @@ -345,12 +344,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.field_visibility_spans.insert(def_id, field_vis); } - fn insert_field_names_extern(&mut self, def_id: DefId) { - let field_names = - self.r.cstore().struct_field_names_untracked(def_id, self.r.tcx.sess).collect(); - self.r.field_names.insert(def_id, field_names); - } - fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { // If any statements are items, we need to create an anonymous module block @@ -748,7 +741,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); // Record field names for error reporting. - self.insert_field_names_local(def_id, vdata); + self.insert_field_def_ids(local_def_id, vdata); self.insert_field_visibilities_local(def_id, vdata); // If this is a tuple or unit struct, define a name @@ -797,7 +790,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); // Record field names for error reporting. - self.insert_field_names_local(def_id, vdata); + self.insert_field_def_ids(local_def_id, vdata); self.insert_field_visibilities_local(def_id, vdata); } @@ -1003,12 +996,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { | Res::SelfCtor(..) | Res::Err => bug!("unexpected resolution: {:?}", res), } - // Record some extra data for better diagnostics. - match res { - Res::Def(DefKind::Struct, def_id) => self.insert_field_names_extern(def_id), - Res::Def(DefKind::Union, def_id) => self.insert_field_names_extern(def_id), - _ => {} - } } fn add_macro_use_binding( @@ -1519,7 +1506,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // Record field names for error reporting. - self.insert_field_names_local(def_id.to_def_id(), &variant.data); + self.insert_field_def_ids(def_id, &variant.data); self.insert_field_visibilities_local(def_id.to_def_id(), &variant.data); visit::walk_variant(self, variant); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 62873342c2e..44a3d4e628e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1581,8 +1581,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )) = binding.kind { let def_id = self.tcx.parent(ctor_def_id); - let fields = self.field_names.get(&def_id)?; - return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()` + return self + .field_def_ids(def_id)? + .iter() + .map(|&field_id| self.def_span(field_id)) + .reduce(Span::to); // None for `struct Foo()` } None } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6a9b1505712..805c2ff280d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1295,19 +1295,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } _ => (": val", "literal", Applicability::HasPlaceholders), }; - let (fields, applicability) = match self.r.field_names.get(&def_id) { - Some(fields) => ( - fields + + let field_ids = self.r.field_def_ids(def_id); + let (fields, applicability) = match field_ids { + Some(field_ids) => ( + field_ids .iter() - .map(|f| format!("{}{}", f.node, tail)) + .map(|&field_id| { + format!("{}{tail}", self.r.tcx.item_name(field_id)) + }) .collect::>() .join(", "), applicability, ), None => ("/* fields */".to_string(), Applicability::HasPlaceholders), }; - let pad = match self.r.field_names.get(&def_id) { - Some(fields) if fields.is_empty() => "", + let pad = match field_ids { + Some(field_ids) if field_ids.is_empty() => "", _ => " ", }; err.span_suggestion( @@ -1451,10 +1455,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ); // Use spans of the tuple struct definition. - self.r - .field_names - .get(&def_id) - .map(|fields| fields.iter().map(|f| f.span).collect::>()) + self.r.field_def_ids(def_id).map(|field_ids| { + field_ids + .iter() + .map(|&field_id| self.r.def_span(field_id)) + .collect::>() + }) } _ => None, }; @@ -1517,9 +1523,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => { let def_id = self.r.tcx.parent(ctor_def_id); err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here")); - let fields = self.r.field_names.get(&def_id).map_or_else( + let fields = self.r.field_def_ids(def_id).map_or_else( || "/* fields */".to_string(), - |fields| vec!["_"; fields.len()].join(", "), + |field_ids| vec!["_"; field_ids.len()].join(", "), ); err.span_suggestion( span, @@ -1600,8 +1606,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) = resolution.full_res() { - if let Some(field_names) = self.r.field_names.get(&did) { - if field_names.iter().any(|&field_name| ident.name == field_name.node) { + if let Some(field_ids) = self.r.field_def_ids(did) { + if field_ids + .iter() + .any(|&field_id| ident.name == self.r.tcx.item_name(field_id)) + { return Some(AssocSuggestion::Field); } } @@ -2015,11 +2024,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } else { let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| { let def_id = self.r.tcx.parent(ctor_def_id); - let has_no_fields = self.r.field_names.get(&def_id).map_or(false, |f| f.is_empty()); match kind { CtorKind::Const => false, - CtorKind::Fn if has_no_fields => false, - _ => true, + CtorKind::Fn => !self + .r + .field_def_ids(def_id) + .map_or(false, |field_ids| field_ids.is_empty()), } }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4277e427c46..ae1d9406467 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -50,7 +50,6 @@ use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::LintBuffer; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; -use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -881,10 +880,7 @@ pub struct Resolver<'a, 'tcx> { /// N.B., this is used only for better diagnostics, not name resolution itself. has_self: LocalDefIdSet, - - /// Names of fields of an item `DefId` accessible with dot syntax. - /// Used for hints during error reporting. - field_names: FxHashMap>>, + field_def_ids: LocalDefIdMap<&'tcx [DefId]>, /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax. /// Used for hints during error reporting. @@ -1249,7 +1245,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { extern_prelude, has_self: Default::default(), - field_names: FxHashMap::default(), + field_def_ids: Default::default(), field_visibility_spans: FxHashMap::default(), determined_imports: Vec::new(), @@ -1877,6 +1873,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + fn field_def_ids(&self, def_id: DefId) -> Option<&'tcx [DefId]> { + match def_id.as_local() { + Some(def_id) => self.field_def_ids.get(&def_id).copied(), + None => Some(self.tcx.associated_item_def_ids(def_id)), + } + } + /// Checks if an expression refers to a function marked with /// `#[rustc_legacy_const_generics]` and returns the argument index list /// from the attribute. diff --git a/tests/ui/empty/empty-struct-tuple-pat.stderr b/tests/ui/empty/empty-struct-tuple-pat.stderr index 8d0f75d204c..45001c79753 100644 --- a/tests/ui/empty/empty-struct-tuple-pat.stderr +++ b/tests/ui/empty/empty-struct-tuple-pat.stderr @@ -46,8 +46,8 @@ LL | XEmpty5(), | help: use the tuple variant pattern syntax instead | -LL | XE::XEmpty5(/* fields */) => (), - | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | XE::XEmpty5() => (), + | ~~~~~~~~~~~~~ help: a unit variant with a similar name exists | LL | XE::XEmpty4 => (), diff --git a/tests/ui/pattern/pat-tuple-field-count-cross.stderr b/tests/ui/pattern/pat-tuple-field-count-cross.stderr index d9295746158..0d7f2e4af69 100644 --- a/tests/ui/pattern/pat-tuple-field-count-cross.stderr +++ b/tests/ui/pattern/pat-tuple-field-count-cross.stderr @@ -113,8 +113,8 @@ LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } | help: use the tuple variant pattern syntax instead | -LL | E1::Z1(/* fields */) => {} - | ~~~~~~~~~~~~~~~~~~~~ +LL | E1::Z1() => {} + | ~~~~~~~~ help: a unit variant with a similar name exists | LL | E1::Z0 => {}