Skip to content

Commit b757ae7

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

File tree

4 files changed

+55
-43
lines changed

4 files changed

+55
-43
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, false));
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: 52 additions & 28 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>, bool),
1015+
OptReadyErr(bool),
1016+
Item(NameBinding<'ra>, bool),
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+
&& matches!(entry.binding.get(), EpeBinding::Item(b, _) if b == 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() {
2179-
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-
}
2188+
let entry = self.extern_prelude.get(&norm_ident).cloned();
2189+
let binding = entry.map(|entry| match entry.binding.get() {
2190+
EpeBinding::Item(binding, finalized) => {
2191+
if finalize && !finalized && entry.introduced_by_item {
2192+
self.record_use(ident, binding, Used::Other);
21852193
}
2186-
binding
2187-
} else {
2194+
EpeBinding::Item(binding, finalize)
2195+
}
2196+
EpeBinding::OptReadyOk(binding, finalized) => {
2197+
if finalize && !finalized {
2198+
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
2199+
}
2200+
EpeBinding::OptReadyOk(binding, finalize)
2201+
}
2202+
EpeBinding::OptReadyErr(finalized) => {
2203+
if finalize && !finalized {
2204+
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
2205+
}
2206+
EpeBinding::OptReadyErr(finalize)
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(finalize),
2217+
};
2218+
let binding = self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
2219+
EpeBinding::OptReadyOk(binding, finalize)
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>`

tests/ui/crate-loading/invalid-rlib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,3 @@
66
#![no_std]
77
use ::foo; //~ ERROR invalid metadata files for crate `foo`
88
//~| NOTE failed to mmap file
9-
//~^^ ERROR invalid metadata files for crate `foo`
10-
//~| NOTE failed to mmap file
11-
//~| NOTE duplicate diagnostic

tests/ui/crate-loading/invalid-rlib.stderr

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@ LL | use ::foo;
66
|
77
= note: failed to mmap file 'auxiliary/libfoo.rlib'
88

9-
error[E0786]: found invalid metadata files for crate `foo`
10-
--> $DIR/invalid-rlib.rs:7:7
11-
|
12-
LL | use ::foo;
13-
| ^^^
14-
|
15-
= note: failed to mmap file 'auxiliary/libfoo.rlib'
16-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
17-
18-
error: aborting due to 2 previous errors
9+
error: aborting due to 1 previous error
1910

2011
For more information about this error, try `rustc --explain E0786`.

0 commit comments

Comments
 (0)