Skip to content

Commit ada8cf9

Browse files
committed
resolve: Unload speculatively resolved crates before freezing cstore
1 parent 4c5ce1f commit ada8cf9

File tree

7 files changed

+57
-16
lines changed

7 files changed

+57
-16
lines changed

Diff for: compiler/rustc_data_structures/src/sync/vec.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ impl<I: Idx, T: Copy> AppendOnlyIndexVec<I, T> {
4141
}
4242
}
4343

44-
#[derive(Default)]
4544
pub struct AppendOnlyVec<T: Copy> {
4645
vec: parking_lot::RwLock<Vec<T>>,
4746
}
@@ -80,6 +79,12 @@ impl<T: Copy + PartialEq> AppendOnlyVec<T> {
8079
}
8180
}
8281

82+
impl<T: Copy> Default for AppendOnlyVec<T> {
83+
fn default() -> Self {
84+
AppendOnlyVec { vec: Default::default() }
85+
}
86+
}
87+
8388
impl<A: Copy> FromIterator<A> for AppendOnlyVec<A> {
8489
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
8590
let this = Self::new();

Diff for: compiler/rustc_metadata/src/creader.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ impl CStore {
196196
CrateMetadataRef { cdata, cstore: self }
197197
}
198198

199+
pub(crate) fn get_crate_data_mut(&mut self, cnum: CrateNum) -> &mut CrateMetadata {
200+
self.metas[cnum].as_mut().unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}"))
201+
}
202+
199203
fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
200204
assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry");
201205
self.metas[cnum] = Some(Box::new(data));
@@ -524,7 +528,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
524528
) -> Option<CrateNum> {
525529
self.used_extern_options.insert(name);
526530
match self.maybe_resolve_crate(name, dep_kind, None) {
527-
Ok(cnum) => Some(cnum),
531+
Ok(cnum) => {
532+
self.cstore.set_used_recursively(cnum);
533+
Some(cnum)
534+
}
528535
Err(err) => {
529536
let missing_core =
530537
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
@@ -1066,6 +1073,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
10661073
pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
10671074
self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
10681075
}
1076+
1077+
pub fn unload_unused_crates(&mut self) {
1078+
for opt_cdata in &mut self.cstore.metas {
1079+
if let Some(cdata) = opt_cdata
1080+
&& !cdata.used
1081+
{
1082+
*opt_cdata = None;
1083+
}
1084+
}
1085+
}
10691086
}
10701087

10711088
fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {

Diff for: compiler/rustc_metadata/src/rmeta/decoder.rs

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ pub(crate) struct CrateMetadata {
107107
private_dep: AtomicBool,
108108
/// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
109109
host_hash: Option<Svh>,
110+
/// The crate was used non-speculatively.
111+
pub used: bool,
110112

111113
/// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
112114
/// and `ExpnId`).
@@ -1822,6 +1824,7 @@ impl CrateMetadata {
18221824
source: Lrc::new(source),
18231825
private_dep: AtomicBool::new(private_dep),
18241826
host_hash,
1827+
used: false,
18251828
extern_crate: Lock::new(None),
18261829
hygiene_context: Default::default(),
18271830
def_key_cache: Default::default(),

Diff for: compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+13
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, Symbol};
2626
use rustc_span::Span;
2727

2828
use std::any::Any;
29+
use std::mem;
2930

3031
use super::{Decodable, DecodeContext, DecodeIterator};
3132

@@ -581,6 +582,18 @@ impl CStore {
581582
) -> Span {
582583
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
583584
}
585+
586+
pub fn set_used_recursively(&mut self, cnum: CrateNum) {
587+
let cdata = self.get_crate_data_mut(cnum);
588+
if !cdata.used {
589+
cdata.used = true;
590+
let dependencies = mem::take(&mut cdata.dependencies);
591+
for dep_cnum in dependencies.iter() {
592+
self.set_used_recursively(dep_cnum);
593+
}
594+
self.get_crate_data_mut(cnum).dependencies = dependencies;
595+
}
596+
}
584597
}
585598

586599
impl CrateStore for CStore {

Diff for: compiler/rustc_resolve/src/late.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
2121
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
2222
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
2323
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
24+
use rustc_metadata::creader::CStore;
2425
use rustc_middle::middle::resolve_bound_vars::Set1;
2526
use rustc_middle::{bug, span_bug};
2627
use rustc_session::config::{CrateType, ResolveDocLinks};
@@ -4455,14 +4456,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
44554456
if let Some(res) = res
44564457
&& let Some(def_id) = res.opt_def_id()
44574458
&& !def_id.is_local()
4458-
&& self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
4459-
&& matches!(
4460-
self.r.tcx.sess.opts.resolve_doc_links,
4461-
ResolveDocLinks::ExportedMetadata
4462-
)
44634459
{
4464-
// Encoding foreign def ids in proc macro crate metadata will ICE.
4465-
return None;
4460+
if self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
4461+
&& matches!(
4462+
self.r.tcx.sess.opts.resolve_doc_links,
4463+
ResolveDocLinks::ExportedMetadata
4464+
)
4465+
{
4466+
// Encoding foreign def ids in proc macro crate metadata will ICE.
4467+
return None;
4468+
}
4469+
// Doc paths should be resolved speculatively and should not produce any
4470+
// diagnostics, but if they are indeed resolved, then we need to keep the
4471+
// corresponding crate alive.
4472+
CStore::from_tcx_mut(self.r.tcx).set_used_recursively(def_id.krate);
44664473
}
44674474
res
44684475
});

Diff for: compiler/rustc_resolve/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16101610
self.tcx
16111611
.sess
16121612
.time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate)));
1613+
self.crate_loader(|c| c.unload_unused_crates());
16131614
});
16141615

16151616
// Make sure we don't mutate the cstore from here on.

Diff for: tests/ui/extern-flag/empty-extern-arg.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
error: extern location for std does not exist:
22

3-
error: `#[panic_handler]` function required, but not found
3+
error: requires `sized` lang_item
44

5-
error: language item required, but not found: `eh_personality`
6-
|
7-
= note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
8-
= help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
9-
10-
error: aborting due to 3 previous errors
5+
error: aborting due to 2 previous errors
116

0 commit comments

Comments
 (0)