1
Fork 0

Auto merge of #108992 - petrochenkov:qcstore2, r=cjgillot

resolve: Querify most cstore access methods (subset)

A subset of https://github.com/rust-lang/rust/pull/108346 that is not on a hot path in any way.
This commit is contained in:
bors 2023-03-14 03:38:42 +00:00
commit bd43458d4c
11 changed files with 169 additions and 250 deletions

View file

@ -26,7 +26,7 @@ use rustc_plugin_impl as plugin;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
use rustc_resolve::Resolver; use rustc_resolve::Resolver;
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, Untracked}; use rustc_session::cstore::{MetadataLoader, Untracked};
use rustc_session::output::filename_for_input; use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind; use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session}; use rustc_session::{Limit, Session};
@ -442,13 +442,9 @@ fn escape_dep_env(symbol: Symbol) -> String {
escaped escaped
} }
fn write_out_deps( fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[PathBuf]) {
sess: &Session,
cstore: &CrateStoreDyn,
outputs: &OutputFilenames,
out_filenames: &[PathBuf],
) {
// Write out dependency rules to the dep-info file if requested // Write out dependency rules to the dep-info file if requested
let sess = tcx.sess;
if !sess.opts.output_types.contains_key(&OutputType::DepInfo) { if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
return; return;
} }
@ -496,9 +492,8 @@ fn write_out_deps(
} }
} }
let cstore = cstore.as_any().downcast_ref::<CStore>().unwrap(); for &cnum in tcx.crates(()) {
for cnum in cstore.crates_untracked() { let source = tcx.used_crate_source(cnum);
let source = cstore.crate_source_untracked(cnum);
if let Some((path, _)) = &source.dylib { if let Some((path, _)) = &source.dylib {
files.push(escape_dep_filename(&path.display().to_string())); files.push(escape_dep_filename(&path.display().to_string()));
} }
@ -612,7 +607,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
} }
} }
write_out_deps(sess, &*tcx.cstore_untracked(), &outputs, &output_paths); write_out_deps(tcx, &outputs, &output_paths);
let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1; && sess.opts.output_types.len() == 1;

View file

@ -8,7 +8,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::{self as ast, *}; use rustc_ast::{self as ast, *};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MappedReadGuard; use rustc_data_structures::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard};
use rustc_expand::base::SyntaxExtension; use rustc_expand::base::SyntaxExtension;
use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions; use rustc_hir::definitions::Definitions;
@ -133,8 +133,14 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
impl CStore { impl CStore {
pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> { pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> {
MappedReadGuard::map(tcx.cstore_untracked(), |c| { ReadGuard::map(tcx.untracked().cstore.read(), |cstore| {
c.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`") cstore.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
})
}
pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> MappedWriteGuard<'_, CStore> {
WriteGuard::map(tcx.untracked().cstore.write(), |cstore| {
cstore.untracked_as_any().downcast_mut().expect("`tcx.cstore` is not a `CStore`")
}) })
} }
@ -268,9 +274,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
) -> Self { ) -> Self {
CrateLoader { tcx, cstore, used_extern_options } CrateLoader { tcx, cstore, used_extern_options }
} }
pub fn cstore(&self) -> &CStore {
&self.cstore
}
fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> { fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
for (cnum, data) in self.cstore.iter_crate_data() { for (cnum, data) in self.cstore.iter_crate_data() {

View file

@ -30,7 +30,6 @@ use rustc_session::cstore::{
}; };
use rustc_session::Session; use rustc_session::Session;
use rustc_span::hygiene::ExpnIndex; use rustc_span::hygiene::ExpnIndex;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
@ -930,7 +929,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess)) self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess))
} }
fn get_visibility(self, id: DefIndex) -> ty::Visibility<DefId> { fn get_visibility(self, id: DefIndex) -> Visibility<DefId> {
self.root self.root
.tables .tables
.visibility .visibility
@ -1134,33 +1133,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.decode((self, sess)) .decode((self, sess))
} }
fn get_struct_field_names(
self,
id: DefIndex,
sess: &'a Session,
) -> impl Iterator<Item = Spanned<Symbol>> + '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_struct_field_visibilities(
self,
id: DefIndex,
) -> impl Iterator<Item = Visibility<DefId>> + 'a {
self.root
.tables
.children
.get(self, id)
.expect("fields not encoded for a struct")
.decode(self)
.map(move |field_index| self.get_visibility(field_index))
}
fn get_inherent_implementations_for_type( fn get_inherent_implementations_for_type(
self, self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View file

@ -15,12 +15,12 @@ use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::middle::stability::DeprecationEntry;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_middle::ty::{self, TyCtxt};
use rustc_session::cstore::{CrateSource, CrateStore}; use rustc_session::cstore::CrateStore;
use rustc_session::{Session, StableCrateId}; use rustc_session::{Session, StableCrateId};
use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{kw, Symbol}; use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use std::any::Any; use std::any::Any;
@ -501,35 +501,18 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
tcx.arena tcx.arena
.alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
}, },
crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()), crates: |tcx, ()| {
tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum))
},
..*providers ..*providers
}; };
} }
impl CStore { impl CStore {
pub fn struct_field_names_untracked<'a>(
&'a self,
def: DefId,
sess: &'a Session,
) -> impl Iterator<Item = Spanned<Symbol>> + 'a {
self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
}
pub fn struct_field_visibilities_untracked(
&self,
def: DefId,
) -> impl Iterator<Item = Visibility<DefId>> + '_ {
self.get_crate_data(def.krate).get_struct_field_visibilities(def.index)
}
pub fn ctor_untracked(&self, def: DefId) -> Option<(CtorKind, DefId)> { pub fn ctor_untracked(&self, def: DefId) -> Option<(CtorKind, DefId)> {
self.get_crate_data(def.krate).get_ctor(def.index) self.get_crate_data(def.krate).get_ctor(def.index)
} }
pub fn visibility_untracked(&self, def: DefId) -> Visibility<DefId> {
self.get_crate_data(def.krate).get_visibility(def.index)
}
pub fn module_children_untracked<'a>( pub fn module_children_untracked<'a>(
&'a self, &'a self,
def_id: DefId, def_id: DefId,
@ -566,14 +549,6 @@ impl CStore {
) )
} }
pub fn fn_has_self_parameter_untracked(&self, def: DefId, sess: &Session) -> bool {
self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index, sess)
}
pub fn crate_source_untracked(&self, cnum: CrateNum) -> Lrc<CrateSource> {
self.get_crate_data(cnum).source.clone()
}
pub fn get_span_untracked(&self, def_id: DefId, sess: &Session) -> Span { pub fn get_span_untracked(&self, def_id: DefId, sess: &Session) -> Span {
self.get_crate_data(def_id.krate).get_span(def_id.index, sess) self.get_crate_data(def_id.krate).get_span(def_id.index, sess)
} }
@ -582,10 +557,6 @@ impl CStore {
self.get_crate_data(def.krate).def_kind(def.index) self.get_crate_data(def.krate).def_kind(def.index)
} }
pub fn crates_untracked(&self) -> impl Iterator<Item = CrateNum> + '_ {
self.iter_crate_data().map(|(cnum, _)| cnum)
}
pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes
} }

View file

@ -29,7 +29,6 @@ use rustc_middle::metadata::ModChild;
use rustc_middle::{bug, ty}; use rustc_middle::{bug, ty};
use rustc_session::cstore::CrateStore; use rustc_session::cstore::CrateStore;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span; use rustc_span::Span;
@ -130,12 +129,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}; };
let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess); let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess);
let span = self.cstore().get_span_untracked(def_id, &self.tcx.sess);
Some(self.new_module( Some(self.new_module(
parent, parent,
ModuleKind::Def(def_kind, def_id, name), ModuleKind::Def(def_kind, def_id, name),
expn_id, expn_id,
span, self.def_span(def_id),
// FIXME: Account for `#[no_implicit_prelude]` attributes. // FIXME: Account for `#[no_implicit_prelude]` attributes.
parent.map_or(false, |module| module.no_implicit_prelude), parent.map_or(false, |module| module.no_implicit_prelude),
)) ))
@ -328,13 +326,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
} }
} }
fn insert_field_names_local(&mut self, def_id: DefId, vdata: &ast::VariantData) { fn insert_field_def_ids(&mut self, def_id: LocalDefId, vdata: &ast::VariantData) {
let field_names = vdata if vdata.fields().iter().any(|field| field.is_placeholder) {
.fields() // The fields are not expanded yet.
.iter() return;
.map(|field| respan(field.span, field.ident.map_or(kw::Empty, |ident| ident.name))) }
.collect(); let def_ids = vdata.fields().iter().map(|field| self.r.local_def_id(field.id).to_def_id());
self.r.field_names.insert(def_id, field_names); 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) { fn insert_field_visibilities_local(&mut self, def_id: DefId, vdata: &ast::VariantData) {
@ -346,12 +344,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.r.field_visibility_spans.insert(def_id, field_vis); 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 { fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
// If any statements are items, we need to create an anonymous module // If any statements are items, we need to create an anonymous module
block block
@ -749,7 +741,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
// Record field names for error reporting. // 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); self.insert_field_visibilities_local(def_id, vdata);
// If this is a tuple or unit struct, define a name // If this is a tuple or unit struct, define a name
@ -789,7 +781,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.r self.r
.struct_constructors .struct_constructors
.insert(def_id, (ctor_res, ctor_vis.to_def_id(), ret_fields)); .insert(local_def_id, (ctor_res, ctor_vis.to_def_id(), ret_fields));
} }
} }
@ -798,7 +790,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
// Record field names for error reporting. // 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); self.insert_field_visibilities_local(def_id, vdata);
} }
@ -1004,32 +996,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
| Res::SelfCtor(..) | Res::SelfCtor(..)
| Res::Err => bug!("unexpected resolution: {:?}", res), | Res::Err => bug!("unexpected resolution: {:?}", res),
} }
// Record some extra data for better diagnostics.
match res {
Res::Def(DefKind::Struct, def_id) => {
let cstore = self.r.cstore();
if let Some((ctor_kind, ctor_def_id)) = cstore.ctor_untracked(def_id) {
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let ctor_vis = cstore.visibility_untracked(ctor_def_id);
let field_visibilities =
cstore.struct_field_visibilities_untracked(def_id).collect();
drop(cstore);
self.r
.struct_constructors
.insert(def_id, (ctor_res, ctor_vis, field_visibilities));
} else {
drop(cstore);
}
self.insert_field_names_extern(def_id)
}
Res::Def(DefKind::Union, def_id) => self.insert_field_names_extern(def_id),
Res::Def(DefKind::AssocFn, def_id) => {
if self.r.cstore().fn_has_self_parameter_untracked(def_id, self.r.tcx.sess) {
self.r.has_self.insert(def_id);
}
}
_ => {}
}
} }
fn add_macro_use_binding( fn add_macro_use_binding(
@ -1426,7 +1392,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS), AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
AssocItemKind::Fn(box Fn { ref sig, .. }) => { AssocItemKind::Fn(box Fn { ref sig, .. }) => {
if sig.decl.has_self() { if sig.decl.has_self() {
self.r.has_self.insert(def_id); self.r.has_self.insert(local_def_id);
} }
(DefKind::AssocFn, ValueNS) (DefKind::AssocFn, ValueNS)
} }
@ -1540,7 +1506,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
} }
// Record field names for error reporting. // 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); self.insert_field_visibilities_local(def_id.to_def_id(), &variant.data);
visit::walk_variant(self, variant); visit::walk_variant(self, variant);

View file

@ -12,7 +12,7 @@ use rustc_errors::{struct_span_err, SuggestionStyle};
use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::PrimTy; use rustc_hir::PrimTy;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
@ -555,25 +555,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return err; return err;
} }
Res::SelfTyAlias { alias_to: def_id, .. } => { Res::SelfTyAlias { alias_to: def_id, .. } => {
if let Some(impl_span) = self.opt_span(def_id) { err.span_label(
err.span_label( reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)),
reduce_impl_span_to_impl_keyword(sm, impl_span), "`Self` type implicitly declared here, by this `impl`",
"`Self` type implicitly declared here, by this `impl`", );
);
}
err.span_label(span, "use a type here instead"); err.span_label(span, "use a type here instead");
return err; return err;
} }
Res::Def(DefKind::TyParam, def_id) => { Res::Def(DefKind::TyParam, def_id) => {
if let Some(span) = self.opt_span(def_id) { err.span_label(self.def_span(def_id), "type parameter from outer function");
err.span_label(span, "type parameter from outer function");
}
def_id def_id
} }
Res::Def(DefKind::ConstParam, def_id) => { Res::Def(DefKind::ConstParam, def_id) => {
if let Some(span) = self.opt_span(def_id) { err.span_label(
err.span_label(span, "const parameter from outer function"); self.def_span(def_id),
} "const parameter from outer function",
);
def_id def_id
} }
_ => { _ => {
@ -589,7 +586,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Try to retrieve the span of the function signature and generate a new // Try to retrieve the span of the function signature and generate a new
// message with a local type or const parameter. // message with a local type or const parameter.
let sugg_msg = "try using a local generic parameter instead"; let sugg_msg = "try using a local generic parameter instead";
let name = self.opt_name(def_id).unwrap_or(sym::T); let name = self.tcx.item_name(def_id);
let (span, snippet) = if span.is_empty() { let (span, snippet) = if span.is_empty() {
let snippet = format!("<{}>", name); let snippet = format!("<{}>", name);
(span, snippet) (span, snippet)
@ -1216,15 +1213,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// a note about editions // a note about editions
let note = if let Some(did) = did { let note = if let Some(did) = did {
let requires_note = !did.is_local() let requires_note = !did.is_local()
&& this.cstore().item_attrs_untracked(did, this.tcx.sess).any( && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
|attr| { |attr| {
if attr.has_name(sym::rustc_diagnostic_item) { [sym::TryInto, sym::TryFrom, sym::FromIterator]
[sym::TryInto, sym::TryFrom, sym::FromIterator] .map(|x| Some(x))
.map(|x| Some(x)) .contains(&attr.value_str())
.contains(&attr.value_str())
} else {
false
}
}, },
); );
@ -1373,8 +1366,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
if ident.name == kw::Default if ident.name == kw::Default
&& let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
&& let Some(span) = self.opt_span(def_id)
{ {
let span = self.def_span(def_id);
let source_map = self.tcx.sess.source_map(); let source_map = self.tcx.sess.source_map();
let head_span = source_map.guess_head_span(span); let head_span = source_map.guess_head_span(span);
if let Ok(head) = source_map.span_to_snippet(head_span) { if let Ok(head) = source_map.span_to_snippet(head_span) {
@ -1450,11 +1443,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(suggestion) if suggestion.candidate == kw::Underscore => return false, Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
Some(suggestion) => suggestion, Some(suggestion) => suggestion,
}; };
let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate { if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
LOCAL_CRATE => self.opt_span(def_id),
_ => Some(self.cstore().get_span_untracked(def_id, self.tcx.sess)),
});
if let Some(def_span) = def_span {
if span.overlaps(def_span) { if span.overlaps(def_span) {
// Don't suggest typo suggestion for itself like in the following: // Don't suggest typo suggestion for itself like in the following:
// error[E0423]: expected function, tuple struct or tuple variant, found struct `X` // error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
@ -1592,8 +1581,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
)) = binding.kind )) = binding.kind
{ {
let def_id = self.tcx.parent(ctor_def_id); let def_id = self.tcx.parent(ctor_def_id);
let fields = self.field_names.get(&def_id)?; return self
return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()` .field_def_ids(def_id)?
.iter()
.map(|&field_id| self.def_span(field_id))
.reduce(Span::to); // None for `struct Foo()`
} }
None None
} }

View file

@ -3376,7 +3376,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
participle: "defined", participle: "defined",
article: res.article(), article: res.article(),
shadowed_binding: res, shadowed_binding: res,
shadowed_binding_span: self.r.opt_span(def_id).expect("const parameter defined outside of local crate"), shadowed_binding_span: self.r.def_span(def_id),
} }
); );
None None

View file

@ -19,7 +19,7 @@ use rustc_errors::{
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::PrimTy; use rustc_hir::PrimTy;
use rustc_session::lint; use rustc_session::lint;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
@ -166,13 +166,6 @@ impl TypoCandidate {
} }
impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
fn def_span(&self, def_id: DefId) -> Option<Span> {
match def_id.krate {
LOCAL_CRATE => self.r.opt_span(def_id),
_ => Some(self.r.cstore().get_span_untracked(def_id, self.r.tcx.sess)),
}
}
fn make_base_error( fn make_base_error(
&mut self, &mut self,
path: &[Segment], path: &[Segment],
@ -191,7 +184,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
span, span,
span_label: match res { span_label: match res {
Res::Def(kind, def_id) if kind == DefKind::TyParam => { Res::Def(kind, def_id) if kind == DefKind::TyParam => {
self.def_span(def_id).map(|span| (span, "found this type parameter")) Some((self.r.def_span(def_id), "found this type parameter"))
} }
_ => None, _ => None,
}, },
@ -1295,28 +1288,30 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} }
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => { PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
let span = find_span(&source, err); let span = find_span(&source, err);
if let Some(span) = self.def_span(def_id) { err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here"));
err.span_label(span, &format!("`{}` defined here", path_str));
}
let (tail, descr, applicability) = match source { let (tail, descr, applicability) = match source {
PathSource::Pat | PathSource::TupleStruct(..) => { PathSource::Pat | PathSource::TupleStruct(..) => {
("", "pattern", Applicability::MachineApplicable) ("", "pattern", Applicability::MachineApplicable)
} }
_ => (": val", "literal", Applicability::HasPlaceholders), _ => (": val", "literal", Applicability::HasPlaceholders),
}; };
let (fields, applicability) = match self.r.field_names.get(&def_id) {
Some(fields) => ( let field_ids = self.r.field_def_ids(def_id);
fields let (fields, applicability) = match field_ids {
Some(field_ids) => (
field_ids
.iter() .iter()
.map(|f| format!("{}{}", f.node, tail)) .map(|&field_id| {
format!("{}{tail}", self.r.tcx.item_name(field_id))
})
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", "), .join(", "),
applicability, applicability,
), ),
None => ("/* fields */".to_string(), Applicability::HasPlaceholders), None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
}; };
let pad = match self.r.field_names.get(&def_id) { let pad = match field_ids {
Some(fields) if fields.is_empty() => "", Some(field_ids) if field_ids.is_empty() => "",
_ => " ", _ => " ",
}; };
err.span_suggestion( err.span_suggestion(
@ -1359,17 +1354,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
if self.r.tcx.sess.is_nightly_build() { if self.r.tcx.sess.is_nightly_build() {
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias"; `type` alias";
if let Some(span) = self.def_span(def_id) { let span = self.r.def_span(def_id);
if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) { if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) {
// The span contains a type alias so we should be able to // The span contains a type alias so we should be able to
// replace `type` with `trait`. // replace `type` with `trait`.
let snip = snip.replacen("type", "trait", 1); let snip = snip.replacen("type", "trait", 1);
err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect); err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect);
} else {
err.span_help(span, msg);
}
} else { } else {
err.help(msg); err.span_help(span, msg);
} }
} }
} }
@ -1408,19 +1400,38 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
self.suggest_using_enum_variant(err, source, def_id, span); self.suggest_using_enum_variant(err, source, def_id, span);
} }
(Res::Def(DefKind::Struct, def_id), source) if ns == ValueNS => { (Res::Def(DefKind::Struct, def_id), source) if ns == ValueNS => {
let (ctor_def, ctor_vis, fields) = let struct_ctor = match def_id.as_local() {
if let Some(struct_ctor) = self.r.struct_constructors.get(&def_id).cloned() { Some(def_id) => self.r.struct_constructors.get(&def_id).cloned(),
if let PathSource::Expr(Some(parent)) = source { None => {
if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind { let ctor = self.r.cstore().ctor_untracked(def_id);
bad_struct_syntax_suggestion(def_id); ctor.map(|(ctor_kind, ctor_def_id)| {
return true; let ctor_res =
} Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let ctor_vis = self.r.tcx.visibility(ctor_def_id);
let field_visibilities = self
.r
.tcx
.associated_item_def_ids(def_id)
.iter()
.map(|field_id| self.r.tcx.visibility(field_id))
.collect();
(ctor_res, ctor_vis, field_visibilities)
})
}
};
let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
if let PathSource::Expr(Some(parent)) = source {
if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
bad_struct_syntax_suggestion(def_id);
return true;
} }
struct_ctor }
} else { struct_ctor
bad_struct_syntax_suggestion(def_id); } else {
return true; bad_struct_syntax_suggestion(def_id);
}; return true;
};
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module); let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
if !is_expected(ctor_def) || is_accessible { if !is_expected(ctor_def) || is_accessible {
@ -1444,10 +1455,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
); );
// Use spans of the tuple struct definition. // Use spans of the tuple struct definition.
self.r self.r.field_def_ids(def_id).map(|field_ids| {
.field_names field_ids
.get(&def_id) .iter()
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>()) .map(|&field_id| self.r.def_span(field_id))
.collect::<Vec<_>>()
})
} }
_ => None, _ => None,
}; };
@ -1493,9 +1506,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
match source { match source {
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => { PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
let span = find_span(&source, err); let span = find_span(&source, err);
if let Some(span) = self.def_span(def_id) { err.span_label(
err.span_label(span, &format!("`{}` defined here", path_str)); self.r.def_span(def_id),
} &format!("`{path_str}` defined here"),
);
err.span_suggestion( err.span_suggestion(
span, span,
"use this syntax instead", "use this syntax instead",
@ -1508,12 +1522,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} }
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => { (Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
let def_id = self.r.tcx.parent(ctor_def_id); let def_id = self.r.tcx.parent(ctor_def_id);
if let Some(span) = self.def_span(def_id) { err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here"));
err.span_label(span, &format!("`{}` defined here", path_str)); let fields = self.r.field_def_ids(def_id).map_or_else(
}
let fields = self.r.field_names.get(&def_id).map_or_else(
|| "/* fields */".to_string(), || "/* fields */".to_string(),
|fields| vec!["_"; fields.len()].join(", "), |field_ids| vec!["_"; field_ids.len()].join(", "),
); );
err.span_suggestion( err.span_suggestion(
span, span,
@ -1594,8 +1606,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) = if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
resolution.full_res() resolution.full_res()
{ {
if let Some(field_names) = self.r.field_names.get(&did) { if let Some(field_ids) = self.r.field_def_ids(did) {
if field_names.iter().any(|&field_name| ident.name == field_name.node) { if field_ids
.iter()
.any(|&field_id| ident.name == self.r.tcx.item_name(field_id))
{
return Some(AssocSuggestion::Field); return Some(AssocSuggestion::Field);
} }
} }
@ -1630,7 +1645,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
) { ) {
let res = binding.res(); let res = binding.res();
if filter_fn(res) { if filter_fn(res) {
if self.r.has_self.contains(&res.def_id()) { let def_id = res.def_id();
let has_self = match def_id.as_local() {
Some(def_id) => self.r.has_self.contains(&def_id),
None => self
.r
.tcx
.fn_arg_names(def_id)
.first()
.map_or(false, |ident| ident.name == kw::SelfLower),
};
if has_self {
return Some(AssocSuggestion::MethodWithSelf { called }); return Some(AssocSuggestion::MethodWithSelf { called });
} else { } else {
match res { match res {
@ -1999,11 +2024,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} else { } else {
let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| { let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| {
let def_id = self.r.tcx.parent(ctor_def_id); 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 { match kind {
CtorKind::Const => false, CtorKind::Const => false,
CtorKind::Fn if has_no_fields => false, CtorKind::Fn => !self
_ => true, .r
.field_def_ids(def_id)
.map_or(false, |field_ids| field_ids.is_empty()),
} }
}; };
@ -2064,9 +2090,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}; };
if def_id.is_local() { if def_id.is_local() {
if let Some(span) = self.def_span(def_id) { err.span_note(self.r.def_span(def_id), "the enum is defined here");
err.span_note(span, "the enum is defined here");
}
} }
} }

View file

@ -35,7 +35,7 @@ use rustc_errors::{
use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData; use rustc_hir::definitions::DefPathData;
use rustc_hir::TraitCandidate; use rustc_hir::TraitCandidate;
@ -48,10 +48,8 @@ use rustc_middle::span_bug;
use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt}; use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
use rustc_session::cstore::CrateStore;
use rustc_session::lint::LintBuffer; use rustc_session::lint::LintBuffer;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; 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::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
@ -881,11 +879,8 @@ pub struct Resolver<'a, 'tcx> {
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>, extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
/// N.B., this is used only for better diagnostics, not name resolution itself. /// N.B., this is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>, has_self: LocalDefIdSet,
field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
/// Names of fields of an item `DefId` accessible with dot syntax.
/// Used for hints during error reporting.
field_names: FxHashMap<DefId, Vec<Spanned<Symbol>>>,
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax. /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
/// Used for hints during error reporting. /// Used for hints during error reporting.
@ -1009,7 +1004,7 @@ pub struct Resolver<'a, 'tcx> {
/// Table for mapping struct IDs into struct constructor IDs, /// Table for mapping struct IDs into struct constructor IDs,
/// it's not used during normal resolution, only for better error reporting. /// it's not used during normal resolution, only for better error reporting.
/// Also includes of list of each fields visibility /// Also includes of list of each fields visibility
struct_constructors: DefIdMap<(Res, ty::Visibility<DefId>, Vec<ty::Visibility<DefId>>)>, struct_constructors: LocalDefIdMap<(Res, ty::Visibility<DefId>, Vec<ty::Visibility<DefId>>)>,
/// Features enabled for this crate. /// Features enabled for this crate.
active_features: FxHashSet<Symbol>, active_features: FxHashSet<Symbol>,
@ -1249,8 +1244,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
prelude: None, prelude: None,
extern_prelude, extern_prelude,
has_self: FxHashSet::default(), has_self: Default::default(),
field_names: FxHashMap::default(), field_def_ids: Default::default(),
field_visibility_spans: FxHashMap::default(), field_visibility_spans: FxHashMap::default(),
determined_imports: Vec::new(), determined_imports: Vec::new(),
@ -1436,9 +1431,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
fn crate_loader<T>(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T { fn crate_loader<T>(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T {
let mut cstore = self.tcx.untracked().cstore.write(); f(&mut CrateLoader::new(
let cstore = cstore.untracked_as_any().downcast_mut().unwrap(); self.tcx,
f(&mut CrateLoader::new(self.tcx, &mut *cstore, &mut self.used_extern_options)) &mut CStore::from_tcx_mut(self.tcx),
&mut self.used_extern_options,
))
} }
fn cstore(&self) -> MappedReadGuard<'_, CStore> { fn cstore(&self) -> MappedReadGuard<'_, CStore> {
@ -1870,20 +1867,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
} }
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate. /// Retrieves definition span of the given `DefId`.
#[inline] fn def_span(&self, def_id: DefId) -> Span {
fn opt_span(&self, def_id: DefId) -> Option<Span> { match def_id.as_local() {
def_id.as_local().map(|def_id| self.tcx.source_span(def_id)) Some(def_id) => self.tcx.source_span(def_id),
None => self.cstore().get_span_untracked(def_id, self.tcx.sess),
}
} }
/// Retrieves the name of the given `DefId`. fn field_def_ids(&self, def_id: DefId) -> Option<&'tcx [DefId]> {
#[inline] match def_id.as_local() {
fn opt_name(&self, def_id: DefId) -> Option<Symbol> { Some(def_id) => self.field_def_ids.get(&def_id).copied(),
let def_key = match def_id.as_local() { None => Some(self.tcx.associated_item_def_ids(def_id)),
Some(def_id) => self.tcx.definitions_untracked().def_key(def_id), }
None => self.cstore().def_key(def_id),
};
def_key.get_opt_name()
} }
/// Checks if an expression refers to a function marked with /// Checks if an expression refers to a function marked with

View file

@ -46,8 +46,8 @@ LL | XEmpty5(),
| |
help: use the tuple variant pattern syntax instead help: use the tuple variant pattern syntax instead
| |
LL | XE::XEmpty5(/* fields */) => (), LL | XE::XEmpty5() => (),
| ~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~
help: a unit variant with a similar name exists help: a unit variant with a similar name exists
| |
LL | XE::XEmpty4 => (), LL | XE::XEmpty4 => (),

View file

@ -113,8 +113,8 @@ LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
| |
help: use the tuple variant pattern syntax instead help: use the tuple variant pattern syntax instead
| |
LL | E1::Z1(/* fields */) => {} LL | E1::Z1() => {}
| ~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~
help: a unit variant with a similar name exists help: a unit variant with a similar name exists
| |
LL | E1::Z0 => {} LL | E1::Z0 => {}