mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 10:18:25 +00:00
Rollup merge of #144746 - petrochenkov:extpreltidy, r=b-naber
resolve: Cleanups and micro-optimizations to extern prelude This is what can be done without changing the structure of `ExternPreludeEntry`, like in https://github.com/rust-lang/rust/pull/144737. See individual commits for details.
This commit is contained in:
commit
2105044784
@ -4519,6 +4519,7 @@ name = "rustc_resolve"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"indexmap",
|
||||
"itertools",
|
||||
"pulldown-cmark",
|
||||
"rustc_arena",
|
||||
|
@ -6,6 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
indexmap = "2.4.0"
|
||||
itertools = "0.12"
|
||||
pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
|
@ -968,7 +968,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
||||
}
|
||||
self.r.potentially_unused_imports.push(import);
|
||||
let imported_binding = self.r.import(binding, import);
|
||||
if parent == self.r.graph_root {
|
||||
if ident.name != kw::Underscore && parent == self.r.graph_root {
|
||||
let ident = ident.normalize_to_macros_2_0();
|
||||
if let Some(entry) = self.r.extern_prelude.get(&ident)
|
||||
&& expansion != LocalExpnId::ROOT
|
||||
@ -984,23 +984,29 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
||||
// more details: https://github.com/rust-lang/rust/pull/111761
|
||||
return;
|
||||
}
|
||||
let entry = self.r.extern_prelude.entry(ident).or_insert(ExternPreludeEntry {
|
||||
binding: Cell::new(None),
|
||||
introduced_by_item: true,
|
||||
});
|
||||
if orig_name.is_some() {
|
||||
entry.introduced_by_item = true;
|
||||
}
|
||||
// Binding from `extern crate` item in source code can replace
|
||||
// a binding from `--extern` on command line here.
|
||||
if !entry.is_import() {
|
||||
entry.binding.set(Some(imported_binding));
|
||||
} else if ident.name != kw::Underscore {
|
||||
self.r.dcx().span_delayed_bug(
|
||||
item.span,
|
||||
format!("it had been define the external module '{ident}' multiple times"),
|
||||
);
|
||||
}
|
||||
|
||||
use indexmap::map::Entry;
|
||||
match self.r.extern_prelude.entry(ident) {
|
||||
Entry::Occupied(mut occupied) => {
|
||||
let entry = occupied.get_mut();
|
||||
if let Some(old_binding) = entry.binding.get()
|
||||
&& old_binding.is_import()
|
||||
{
|
||||
let msg = format!("extern crate `{ident}` already in extern prelude");
|
||||
self.r.tcx.dcx().span_delayed_bug(item.span, msg);
|
||||
} else {
|
||||
// Binding from `extern crate` item in source code can replace
|
||||
// a binding from `--extern` on command line here.
|
||||
entry.binding.set(Some(imported_binding));
|
||||
entry.introduced_by_item = orig_name.is_some();
|
||||
}
|
||||
entry
|
||||
}
|
||||
Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry {
|
||||
binding: Cell::new(Some(imported_binding)),
|
||||
introduced_by_item: true,
|
||||
}),
|
||||
};
|
||||
}
|
||||
self.r.define_binding_local(parent, ident, TypeNS, imported_binding);
|
||||
}
|
||||
|
@ -1098,7 +1098,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
}
|
||||
}
|
||||
Scope::ExternPrelude => {
|
||||
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
|
||||
suggestions.extend(this.extern_prelude.keys().filter_map(|ident| {
|
||||
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
|
||||
filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res))
|
||||
}));
|
||||
@ -1409,7 +1409,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
);
|
||||
|
||||
if lookup_ident.span.at_least_rust_2018() {
|
||||
for ident in self.extern_prelude.clone().into_keys() {
|
||||
for &ident in self.extern_prelude.keys() {
|
||||
if ident.span.from_expansion() {
|
||||
// Idents are adjusted to the root context before being
|
||||
// resolved in the extern prelude, so reporting this to the
|
||||
|
@ -2476,19 +2476,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
||||
} else {
|
||||
// Items from the prelude
|
||||
if !module.no_implicit_prelude {
|
||||
let extern_prelude = self.r.extern_prelude.clone();
|
||||
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
|
||||
self.r
|
||||
.cstore_mut()
|
||||
.maybe_process_path_extern(self.r.tcx, ident.name)
|
||||
.and_then(|crate_id| {
|
||||
let crate_mod =
|
||||
Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||
|
||||
filter_fn(crate_mod).then(|| {
|
||||
TypoSuggestion::typo_from_ident(*ident, crate_mod)
|
||||
})
|
||||
})
|
||||
names.extend(self.r.extern_prelude.keys().flat_map(|ident| {
|
||||
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
|
||||
filter_fn(res)
|
||||
.then_some(TypoSuggestion::typo_from_ident(*ident, res))
|
||||
}));
|
||||
|
||||
if let Some(prelude) = self.r.prelude {
|
||||
|
@ -1487,13 +1487,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
let mut invocation_parents = FxHashMap::default();
|
||||
invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT);
|
||||
|
||||
let mut extern_prelude: FxIndexMap<Ident, ExternPreludeEntry<'_>> = tcx
|
||||
let mut extern_prelude: FxIndexMap<_, _> = tcx
|
||||
.sess
|
||||
.opts
|
||||
.externs
|
||||
.iter()
|
||||
.filter(|(_, entry)| entry.add_prelude)
|
||||
.map(|(name, _)| (Ident::from_str(name), Default::default()))
|
||||
.filter_map(|(name, entry)| {
|
||||
// Make sure `self`, `super`, `_` etc do not get into extern prelude.
|
||||
// FIXME: reject `--extern self` and similar in option parsing instead.
|
||||
if entry.add_prelude
|
||||
&& let name = Symbol::intern(name)
|
||||
&& name.can_be_raw()
|
||||
{
|
||||
Some((Ident::with_dummy_span(name), Default::default()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !attr::contains_name(attrs, sym::no_core) {
|
||||
@ -2168,40 +2178,42 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
}
|
||||
|
||||
fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> {
|
||||
if ident.is_path_segment_keyword() {
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
return None;
|
||||
}
|
||||
|
||||
let norm_ident = ident.normalize_to_macros_2_0();
|
||||
let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| {
|
||||
Some(if let Some(binding) = entry.binding.get() {
|
||||
let mut record_use = None;
|
||||
let entry = self.extern_prelude.get(&ident.normalize_to_macros_2_0());
|
||||
let binding = entry.and_then(|entry| match entry.binding.get() {
|
||||
Some(binding) if binding.is_import() => {
|
||||
if finalize {
|
||||
if !entry.is_import() {
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
|
||||
} else if entry.introduced_by_item {
|
||||
self.record_use(ident, binding, Used::Other);
|
||||
}
|
||||
record_use = Some(binding);
|
||||
}
|
||||
binding
|
||||
} else {
|
||||
Some(binding)
|
||||
}
|
||||
Some(binding) => {
|
||||
if finalize {
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
|
||||
}
|
||||
Some(binding)
|
||||
}
|
||||
None => {
|
||||
let crate_id = if finalize {
|
||||
let Some(crate_id) =
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
|
||||
else {
|
||||
return Some(self.dummy_binding);
|
||||
};
|
||||
crate_id
|
||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
|
||||
} else {
|
||||
self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)?
|
||||
self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
|
||||
};
|
||||
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT)
|
||||
})
|
||||
match crate_id {
|
||||
Some(crate_id) => {
|
||||
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||
let binding =
|
||||
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
|
||||
entry.binding.set(Some(binding));
|
||||
Some(binding)
|
||||
}
|
||||
None => finalize.then_some(self.dummy_binding),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(entry) = self.extern_prelude.get(&norm_ident) {
|
||||
entry.binding.set(binding);
|
||||
if let Some(binding) = record_use {
|
||||
self.record_use(ident, binding, Used::Scope);
|
||||
}
|
||||
|
||||
binding
|
||||
|
Loading…
x
Reference in New Issue
Block a user