Skip to content

Commit 3f18306

Browse files
committed
Index the crate before creating the TyCtxt.
1 parent 50c56c5 commit 3f18306

File tree

5 files changed

+90
-46
lines changed

5 files changed

+90
-46
lines changed

compiler/rustc_ast_lowering/src/item.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
use super::ResolverAstLoweringExt;
2-
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
32
use super::{FnDeclKind, LoweringContext, ParamMode};
3+
use super::{ImplTraitContext, ImplTraitPosition};
44

55
use rustc_ast::ptr::P;
66
use rustc_ast::visit::AssocCtxt;
77
use rustc_ast::*;
88
use rustc_data_structures::fx::FxHashMap;
99
use rustc_data_structures::sorted_map::SortedMap;
10+
use rustc_data_structures::steal::Steal;
1011
use rustc_errors::struct_span_err;
1112
use rustc_hir as hir;
1213
use rustc_hir::def::{DefKind, Res};
1314
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
1415
use rustc_index::vec::{Idx, IndexVec};
15-
use rustc_middle::ty::{ResolverOutputs, TyCtxt};
16+
use rustc_middle::ty::{AstOwner, ResolverOutputs, TyCtxt};
1617
use rustc_session::utils::NtToTokenstream;
1718
use rustc_span::source_map::DesugaringKind;
1819
use rustc_span::symbol::{kw, sym, Ident};
@@ -27,7 +28,7 @@ pub(super) struct ItemLowerer<'a, 'hir> {
2728
pub(super) tcx: TyCtxt<'hir>,
2829
pub(super) resolver: &'hir ResolverOutputs,
2930
pub(super) nt_to_tokenstream: NtToTokenstream,
30-
pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>,
31+
pub(super) ast_index: &'a IndexVec<LocalDefId, Steal<AstOwner>>,
3132
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
3233
}
3334

@@ -107,13 +108,13 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
107108
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
108109
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
109110
if let hir::MaybeOwner::Phantom = self.owners[def_id] {
110-
let node = self.ast_index[def_id];
111+
let node = self.ast_index[def_id].steal();
111112
match node {
112-
AstOwner::NonOwner => {}
113-
AstOwner::Crate(c) => self.lower_crate(c),
114-
AstOwner::Item(item) => self.lower_item(item),
115-
AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt),
116-
AstOwner::ForeignItem(item) => self.lower_foreign_item(item),
113+
AstOwner::NonOwner | AstOwner::Synthetic(..) => {}
114+
AstOwner::Crate(c) => self.lower_crate(&c),
115+
AstOwner::Item(item) => self.lower_item(&item),
116+
AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(&item, ctxt),
117+
AstOwner::ForeignItem(item) => self.lower_foreign_item(&item),
117118
}
118119
}
119120

compiler/rustc_ast_lowering/src/lib.rs

+56-29
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ use rustc_ast_pretty::pprust;
4646
use rustc_data_structures::captures::Captures;
4747
use rustc_data_structures::fingerprint::Fingerprint;
4848
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
49+
use rustc_data_structures::owning_ref::OwningRef;
4950
use rustc_data_structures::sorted_map::SortedMap;
5051
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
52+
use rustc_data_structures::steal::Steal;
5153
use rustc_data_structures::sync::Lrc;
5254
use rustc_errors::struct_span_err;
5355
use rustc_hir as hir;
@@ -56,7 +58,7 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
5658
use rustc_hir::definitions::DefPathData;
5759
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
5860
use rustc_index::vec::{Idx, IndexVec};
59-
use rustc_middle::ty::{ResolverOutputs, TyCtxt};
61+
use rustc_middle::ty::{AstOwner, ResolverOutputs, TyCtxt};
6062
use rustc_session::parse::feature_err;
6163
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
6264
use rustc_session::Session;
@@ -341,54 +343,80 @@ impl FnDeclKind {
341343
}
342344
}
343345

344-
#[derive(Copy, Clone)]
345-
enum AstOwner<'a> {
346-
NonOwner,
347-
Crate(&'a ast::Crate),
348-
Item(&'a ast::Item),
349-
AssocItem(&'a ast::AssocItem, visit::AssocCtxt),
350-
ForeignItem(&'a ast::ForeignItem),
351-
}
352-
353-
fn index_crate<'a>(
346+
pub fn index_crate(
354347
node_id_to_def_id: &FxHashMap<NodeId, LocalDefId>,
355-
krate: &'a Crate,
356-
) -> IndexVec<LocalDefId, AstOwner<'a>> {
357-
let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() };
358-
indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner);
359-
indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate);
360-
visit::walk_crate(&mut indexer, krate);
348+
krate: Lrc<Crate>,
349+
) -> IndexVec<LocalDefId, Steal<AstOwner>> {
350+
let mut indexer =
351+
Indexer { node_id_to_def_id, krate: OwningRef::new(krate.clone()), index: IndexVec::new() };
352+
indexer.index.ensure_contains_elem(CRATE_DEF_ID, || Steal::new(AstOwner::NonOwner));
353+
indexer.index[CRATE_DEF_ID] = Steal::new(AstOwner::Crate(krate.clone()));
354+
visit::walk_crate(&mut indexer, &krate);
361355
return indexer.index;
362356

363-
struct Indexer<'s, 'a> {
357+
struct Indexer<'s> {
364358
node_id_to_def_id: &'s FxHashMap<NodeId, LocalDefId>,
365-
index: IndexVec<LocalDefId, AstOwner<'a>>,
359+
krate: OwningRef<Lrc<Crate>, Crate>,
360+
index: IndexVec<LocalDefId, Steal<AstOwner>>,
361+
}
362+
363+
impl Indexer<'_> {
364+
fn visit_item_id_use_tree(&mut self, tree: &UseTree, parent: LocalDefId) {
365+
match tree.kind {
366+
UseTreeKind::Glob => {}
367+
UseTreeKind::Simple(_, id1, id2) => {
368+
for id in &[id1, id2] {
369+
let def_id = self.node_id_to_def_id[id];
370+
self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner));
371+
self.index[def_id] = Steal::new(AstOwner::Synthetic(parent));
372+
}
373+
}
374+
UseTreeKind::Nested(ref nested_vec) => {
375+
for &(ref nested, id) in nested_vec {
376+
let def_id = self.node_id_to_def_id[&id];
377+
self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner));
378+
self.index[def_id] = Steal::new(AstOwner::Synthetic(parent));
379+
380+
self.visit_item_id_use_tree(nested, def_id);
381+
}
382+
}
383+
}
384+
}
366385
}
367386

368-
impl<'a> visit::Visitor<'a> for Indexer<'_, 'a> {
387+
impl<'a> visit::Visitor<'a> for Indexer<'_> {
369388
fn visit_attribute(&mut self, _: &'a Attribute) {
370389
// We do not want to lower expressions that appear in attributes,
371390
// as they are not accessible to the rest of the HIR.
372391
}
373392

374393
fn visit_item(&mut self, item: &'a ast::Item) {
375394
let def_id = self.node_id_to_def_id[&item.id];
376-
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
377-
self.index[def_id] = AstOwner::Item(item);
395+
// SAFETY: the visitor guarantees the item ref comes from krate.
396+
let item_ref = self.krate.clone().map(|_| unsafe { &*(item as *const _) });
397+
self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner));
398+
self.index[def_id] = Steal::new(AstOwner::Item(item_ref));
399+
if let ItemKind::Use(ref use_tree) = item.kind {
400+
self.visit_item_id_use_tree(use_tree, def_id);
401+
}
378402
visit::walk_item(self, item)
379403
}
380404

381405
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) {
382406
let def_id = self.node_id_to_def_id[&item.id];
383-
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
384-
self.index[def_id] = AstOwner::AssocItem(item, ctxt);
407+
// SAFETY: the visitor guarantees the item ref comes from krate.
408+
let item_ref = self.krate.clone().map(|_| unsafe { &*(item as *const _) });
409+
self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner));
410+
self.index[def_id] = Steal::new(AstOwner::AssocItem(item_ref, ctxt));
385411
visit::walk_assoc_item(self, item, ctxt);
386412
}
387413

388414
fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) {
389415
let def_id = self.node_id_to_def_id[&item.id];
390-
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
391-
self.index[def_id] = AstOwner::ForeignItem(item);
416+
// SAFETY: the visitor guarantees the item ref comes from krate.
417+
let item_ref = self.krate.clone().map(|_| unsafe { &*(item as *const _) });
418+
self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner));
419+
self.index[def_id] = Steal::new(AstOwner::ForeignItem(item_ref));
392420
visit::walk_foreign_item(self, item);
393421
}
394422
}
@@ -419,13 +447,12 @@ fn compute_hir_hash(
419447

420448
pub fn lower_crate<'hir>(
421449
tcx: TyCtxt<'hir>,
422-
krate: &Crate,
423450
nt_to_tokenstream: NtToTokenstream,
424451
) -> hir::Crate<'hir> {
425452
let _prof_timer = tcx.sess.prof.verbose_generic_activity("hir_lowering");
426453

427454
let resolver = tcx.resolutions(());
428-
let ast_index = index_crate(&resolver.node_id_to_def_id, krate);
455+
let ast_index = &tcx.untracked_crate;
429456

430457
let mut owners = IndexVec::from_fn_n(
431458
|_| hir::MaybeOwner::Phantom,
@@ -437,7 +464,7 @@ pub fn lower_crate<'hir>(
437464
tcx,
438465
resolver,
439466
nt_to_tokenstream,
440-
ast_index: &ast_index,
467+
ast_index: ast_index,
441468
owners: &mut owners,
442469
}
443470
.lower_node(def_id);

compiler/rustc_interface/src/passes.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -492,13 +492,9 @@ pub fn configure_and_expand(
492492

493493
fn lower_to_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> Crate<'tcx> {
494494
let sess = tcx.sess;
495-
let krate = tcx.untracked_crate.steal();
496495

497496
// Lower AST to HIR.
498-
let hir_crate = rustc_ast_lowering::lower_crate(tcx, &krate, rustc_parse::nt_to_tokenstream);
499-
500-
// Drop AST to free memory
501-
sess.time("drop_ast", || std::mem::drop(krate));
497+
let hir_crate = rustc_ast_lowering::lower_crate(tcx, rustc_parse::nt_to_tokenstream);
502498

503499
// Discard hygiene data, which isn't required after lowering to HIR.
504500
if !sess.opts.debugging_opts.keep_hygiene_data {
@@ -835,6 +831,7 @@ pub fn create_global_ctxt<'tcx>(
835831
dep_graph.assert_ignored();
836832

837833
let (definitions, cstore, resolver_outputs) = BoxedResolver::to_resolver_outputs(resolver);
834+
let krate = rustc_ast_lowering::index_crate(&resolver_outputs.node_id_to_def_id, krate);
838835

839836
let sess = &compiler.session();
840837
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);

compiler/rustc_middle/src/ty/context.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ pub struct GlobalCtxt<'tcx> {
10291029

10301030
/// Output of the resolver.
10311031
pub(crate) untracked_resolutions: ty::ResolverOutputs,
1032-
pub untracked_crate: Steal<Lrc<ast::Crate>>,
1032+
pub untracked_crate: IndexVec<LocalDefId, Steal<ty::AstOwner>>,
10331033

10341034
/// This provides access to the incremental compilation on-disk cache for query results.
10351035
/// Do not access this directly. It is only meant to be used by
@@ -1170,7 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> {
11701170
definitions: Definitions,
11711171
cstore: Box<CrateStoreDyn>,
11721172
untracked_resolutions: ty::ResolverOutputs,
1173-
krate: Lrc<ast::Crate>,
1173+
untracked_crate: IndexVec<LocalDefId, Steal<ty::AstOwner>>,
11741174
dep_graph: DepGraph,
11751175
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
11761176
queries: &'tcx dyn query::QueryEngine<'tcx>,
@@ -1200,7 +1200,7 @@ impl<'tcx> TyCtxt<'tcx> {
12001200
lifetimes: common_lifetimes,
12011201
consts: common_consts,
12021202
untracked_resolutions,
1203-
untracked_crate: Steal::new(krate),
1203+
untracked_crate,
12041204
on_disk_cache,
12051205
queries,
12061206
query_caches: query::QueryCaches::default(),

compiler/rustc_middle/src/ty/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ use rustc_ast::node_id::NodeMap;
3333
use rustc_attr as attr;
3434
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
3535
use rustc_data_structures::intern::{Interned, WithStableHash};
36+
use rustc_data_structures::owning_ref::OwningRef;
3637
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
38+
use rustc_data_structures::sync::Lrc;
3739
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
3840
use rustc_hir as hir;
3941
use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
@@ -128,6 +130,23 @@ mod sty;
128130

129131
pub type RegisteredTools = FxHashSet<Ident>;
130132

133+
/// Pointers to parts of the AST to index it.
134+
/// We use OwningRef to release memory when all the owners have been taken.
135+
pub enum AstOwner {
136+
NonOwner,
137+
Synthetic(LocalDefId),
138+
Crate(Lrc<ast::Crate>),
139+
Item(OwningRef<Lrc<ast::Crate>, ast::Item>),
140+
AssocItem(OwningRef<Lrc<ast::Crate>, ast::AssocItem>, ast::visit::AssocCtxt),
141+
ForeignItem(OwningRef<Lrc<ast::Crate>, ast::ForeignItem>),
142+
}
143+
144+
impl AstOwner {
145+
pub fn expect_crate(&self) -> &Lrc<ast::Crate> {
146+
if let AstOwner::Crate(c) = self { c } else { panic!() }
147+
}
148+
}
149+
131150
#[derive(Debug)]
132151
pub struct ResolverOutputs {
133152
pub visibilities: FxHashMap<LocalDefId, Visibility>,

0 commit comments

Comments
 (0)