Skip to content

Commit 9b02f88

Browse files
committed
resolve: Unload speculatively resolved crates before freezing cstore
1 parent e21f4cd commit 9b02f88

File tree

6 files changed

+52
-16
lines changed

6 files changed

+52
-16
lines changed

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
534534
) -> Option<CrateNum> {
535535
self.used_extern_options.insert(name);
536536
match self.maybe_resolve_crate(name, dep_kind, None) {
537-
Ok(cnum) => Some(cnum),
537+
Ok(cnum) => {
538+
self.cstore.set_used_recursively(cnum);
539+
Some(cnum)
540+
}
538541
Err(err) => {
539542
let missing_core =
540543
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
@@ -1067,6 +1070,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
10671070
pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
10681071
self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
10691072
}
1073+
1074+
pub fn unload_unused_crates(&mut self) {
1075+
for opt_cdata in &mut self.cstore.metas {
1076+
if let Some(cdata) = opt_cdata
1077+
&& !cdata.used()
1078+
{
1079+
*opt_cdata = None;
1080+
}
1081+
}
1082+
}
10701083
}
10711084

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

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

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

110112
/// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
111113
/// and `ExpnId`).
@@ -1810,6 +1812,7 @@ impl CrateMetadata {
18101812
source: Lrc::new(source),
18111813
private_dep,
18121814
host_hash,
1815+
used: false,
18131816
extern_crate: None,
18141817
hygiene_context: Default::default(),
18151818
def_key_cache: Default::default(),
@@ -1859,6 +1862,10 @@ impl CrateMetadata {
18591862
self.private_dep &= private_dep;
18601863
}
18611864

1865+
pub(crate) fn used(&self) -> bool {
1866+
self.used
1867+
}
1868+
18621869
pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
18631870
self.root.required_panic_strategy
18641871
}

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

+14-1
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

@@ -569,12 +570,24 @@ impl CStore {
569570
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
570571
}
571572

573+
pub fn set_used_recursively(&mut self, cnum: CrateNum) {
574+
let cmeta = self.get_crate_data_mut(cnum);
575+
if !cmeta.used {
576+
cmeta.used = true;
577+
let dependencies = mem::take(&mut cmeta.dependencies);
578+
for &dep_cnum in &dependencies {
579+
self.set_used_recursively(dep_cnum);
580+
}
581+
self.get_crate_data_mut(cnum).dependencies = dependencies;
582+
}
583+
}
584+
572585
pub(crate) fn update_extern_crate(&mut self, cnum: CrateNum, extern_crate: ExternCrate) {
573586
let cmeta = self.get_crate_data_mut(cnum);
574587
if cmeta.update_extern_crate(extern_crate) {
575588
// Propagate the extern crate info to dependencies if it was updated.
576589
let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate };
577-
let dependencies = std::mem::take(&mut cmeta.dependencies);
590+
let dependencies = mem::take(&mut cmeta.dependencies);
578591
for &dep_cnum in &dependencies {
579592
self.update_extern_crate(dep_cnum, extern_crate);
580593
}

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)