Skip to content

Commit f9cf5ef

Browse files
Auto merge of #144737 - petrochenkov:extprelcache, r=<try>
[WIP] resolve: Better caching for unsuccessful crate resolutions
2 parents 64ca23b + 3d03332 commit f9cf5ef

File tree

2 files changed

+53
-29
lines changed

2 files changed

+53
-29
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
985985
return;
986986
}
987987
let entry = self.r.extern_prelude.entry(ident).or_insert(ExternPreludeEntry {
988-
binding: Cell::new(None),
988+
binding: Cell::new(crate::EpeBinding::OptPending),
989989
introduced_by_item: true,
990990
});
991991
if orig_name.is_some() {
@@ -994,7 +994,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
994994
// Binding from `extern crate` item in source code can replace
995995
// a binding from `--extern` on command line here.
996996
if !entry.is_import() {
997-
entry.binding.set(Some(imported_binding));
997+
entry.binding.set(crate::EpeBinding::Item(imported_binding));
998998
} else if ident.name != kw::Underscore {
999999
self.r.dcx().span_delayed_bug(
10001000
item.span,

compiler/rustc_resolve/src/lib.rs

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,15 +1007,24 @@ impl<'ra> NameBindingData<'ra> {
10071007
}
10081008
}
10091009

1010+
#[derive(Default, Clone, Copy, PartialEq)]
1011+
enum EpeBinding<'ra> {
1012+
#[default]
1013+
OptPending,
1014+
OptReadyOk(NameBinding<'ra>),
1015+
OptReadyErr,
1016+
Item(NameBinding<'ra>),
1017+
}
1018+
10101019
#[derive(Default, Clone)]
10111020
struct ExternPreludeEntry<'ra> {
1012-
binding: Cell<Option<NameBinding<'ra>>>,
1021+
binding: Cell<EpeBinding<'ra>>,
10131022
introduced_by_item: bool,
10141023
}
10151024

10161025
impl ExternPreludeEntry<'_> {
10171026
fn is_import(&self) -> bool {
1018-
self.binding.get().is_some_and(|binding| binding.is_import())
1027+
matches!(self.binding.get(), EpeBinding::Item(..))
10191028
}
10201029
}
10211030

@@ -2011,7 +2020,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20112020
// but not introduce it, as used if they are accessed from lexical scope.
20122021
if used == Used::Scope {
20132022
if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
2014-
if !entry.introduced_by_item && entry.binding.get() == Some(used_binding) {
2023+
if !entry.introduced_by_item
2024+
&& entry.binding.get() == EpeBinding::Item(used_binding)
2025+
{
20152026
return;
20162027
}
20172028
}
@@ -2174,37 +2185,50 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
21742185
}
21752186

21762187
let norm_ident = ident.normalize_to_macros_2_0();
2177-
let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| {
2178-
Some(if let Some(binding) = entry.binding.get() {
2188+
let entry = self.extern_prelude.get(&norm_ident).cloned();
2189+
let binding = entry.map(|entry| match entry.binding.get() {
2190+
EpeBinding::Item(binding) => {
2191+
if finalize && entry.introduced_by_item {
2192+
self.record_use(ident, binding, Used::Other);
2193+
}
2194+
EpeBinding::Item(binding)
2195+
}
2196+
EpeBinding::OptReadyOk(binding) => {
21792197
if finalize {
2180-
if !entry.is_import() {
2181-
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
2182-
} else if entry.introduced_by_item {
2183-
self.record_use(ident, binding, Used::Other);
2184-
}
2198+
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
21852199
}
2186-
binding
2187-
} else {
2200+
EpeBinding::OptReadyOk(binding)
2201+
}
2202+
EpeBinding::OptReadyErr => {
2203+
if finalize {
2204+
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
2205+
}
2206+
EpeBinding::OptReadyErr
2207+
}
2208+
EpeBinding::OptPending => {
21882209
let crate_id = if finalize {
2189-
let Some(crate_id) =
2190-
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
2191-
else {
2192-
return Some(self.dummy_binding);
2193-
};
2194-
crate_id
2210+
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
21952211
} else {
2196-
self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)?
2212+
self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
21972213
};
2198-
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
2199-
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT)
2200-
})
2214+
let res = match crate_id {
2215+
Some(crate_id) => Res::Def(DefKind::Mod, crate_id.as_def_id()),
2216+
None => return EpeBinding::OptReadyErr,
2217+
};
2218+
let binding = self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
2219+
EpeBinding::OptReadyOk(binding)
2220+
}
22012221
});
22022222

2203-
if let Some(entry) = self.extern_prelude.get(&norm_ident) {
2204-
entry.binding.set(binding);
2205-
}
2206-
2207-
binding
2223+
binding.and_then(|binding| {
2224+
self.extern_prelude[&norm_ident].binding.set(binding);
2225+
match binding {
2226+
EpeBinding::Item(binding) | EpeBinding::OptReadyOk(binding) => Some(binding),
2227+
EpeBinding::OptReadyErr if finalize => Some(self.dummy_binding),
2228+
EpeBinding::OptReadyErr => None,
2229+
EpeBinding::OptPending => unreachable!(),
2230+
}
2231+
})
22082232
}
22092233

22102234
/// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>`

0 commit comments

Comments
 (0)