Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6ea1df2

Browse files
authoredNov 29, 2019
Rollup merge of #66791 - cjgillot:arena, r=Mark-Simulacrum
Handle GlobalCtxt directly from librustc_interface query system This PR constructs the `GlobalCtxt` as a member of the `Queries` in librustc_interface. This simplifies the code to construct it, at the expense of added complexity in the query control flow. This allows to handle the arenas directly from librustc_interface. Based on #66707 r? @Zoxc
2 parents 56203be + 1e12f39 commit 6ea1df2

File tree

10 files changed

+328
-256
lines changed

10 files changed

+328
-256
lines changed
 

‎src/librustc/arena.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ macro_rules! arena_types {
9393
rustc::hir::def_id::CrateNum
9494
>
9595
>,
96+
[few] hir_forest: rustc::hir::map::Forest,
9697
[few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
9798
syntax::symbol::Symbol,
9899
rustc::hir::def_id::DefId,

‎src/librustc/hir/map/mod.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ pub struct Map<'hir> {
200200

201201
map: HirEntryMap<'hir>,
202202

203-
definitions: &'hir Definitions,
203+
definitions: Definitions,
204204

205205
/// The reverse mapping of `node_to_hir_id`.
206206
hir_to_node_id: FxHashMap<HirId, NodeId>,
@@ -267,8 +267,8 @@ impl<'hir> Map<'hir> {
267267
}
268268

269269
#[inline]
270-
pub fn definitions(&self) -> &'hir Definitions {
271-
self.definitions
270+
pub fn definitions(&self) -> &Definitions {
271+
&self.definitions
272272
}
273273

274274
pub fn def_key(&self, def_id: DefId) -> DefKey {
@@ -1251,7 +1251,7 @@ impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
12511251
pub fn map_crate<'hir>(sess: &crate::session::Session,
12521252
cstore: &CrateStoreDyn,
12531253
forest: &'hir Forest,
1254-
definitions: &'hir Definitions)
1254+
definitions: Definitions)
12551255
-> Map<'hir> {
12561256
let _prof_timer = sess.prof.generic_activity("build_hir_map");
12571257

@@ -1260,7 +1260,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session,
12601260
.map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
12611261

12621262
let (map, crate_hash) = {
1263-
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
1263+
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore);
12641264

12651265
let mut collector = NodeCollector::root(sess,
12661266
&forest.krate,

‎src/librustc/ty/context.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> {
995995
}
996996

997997
pub struct GlobalCtxt<'tcx> {
998-
pub arena: WorkerLocal<Arena<'tcx>>,
998+
pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
999999

10001000
interners: CtxtInterners<'tcx>,
10011001

@@ -1170,6 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> {
11701170
local_providers: ty::query::Providers<'tcx>,
11711171
extern_providers: ty::query::Providers<'tcx>,
11721172
arenas: &'tcx AllArenas,
1173+
arena: &'tcx WorkerLocal<Arena<'tcx>>,
11731174
resolutions: ty::ResolverOutputs,
11741175
hir: hir_map::Map<'tcx>,
11751176
on_disk_query_result_cache: query::OnDiskCache<'tcx>,
@@ -1225,7 +1226,7 @@ impl<'tcx> TyCtxt<'tcx> {
12251226
sess: s,
12261227
lint_store,
12271228
cstore,
1228-
arena: WorkerLocal::new(|_| Arena::default()),
1229+
arena,
12291230
interners,
12301231
dep_graph,
12311232
prof: s.prof.clone(),

‎src/librustc_driver/lib.rs‎

Lines changed: 99 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -283,120 +283,127 @@ pub fn run_compiler(
283283
return sess.compile_status();
284284
}
285285

286-
compiler.parse()?;
287-
288-
if let Some(ppm) = &sess.opts.pretty {
289-
if ppm.needs_ast_map() {
290-
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
291-
let expanded_crate = compiler.expansion()?.take().0;
292-
pretty::print_after_hir_lowering(
293-
tcx,
294-
compiler.input(),
295-
&expanded_crate,
286+
let linker = compiler.enter(|queries| {
287+
let early_exit = || sess.compile_status().map(|_| None);
288+
queries.parse()?;
289+
290+
if let Some(ppm) = &sess.opts.pretty {
291+
if ppm.needs_ast_map() {
292+
queries.global_ctxt()?.peek_mut().enter(|tcx| {
293+
let expanded_crate = queries.expansion()?.take().0;
294+
pretty::print_after_hir_lowering(
295+
tcx,
296+
compiler.input(),
297+
&expanded_crate,
298+
*ppm,
299+
compiler.output_file().as_ref().map(|p| &**p),
300+
);
301+
Ok(())
302+
})?;
303+
} else {
304+
let krate = queries.parse()?.take();
305+
pretty::print_after_parsing(
306+
sess,
307+
&compiler.input(),
308+
&krate,
296309
*ppm,
297310
compiler.output_file().as_ref().map(|p| &**p),
298311
);
299-
Ok(())
300-
})?;
301-
} else {
302-
let krate = compiler.parse()?.take();
303-
pretty::print_after_parsing(
304-
sess,
305-
&compiler.input(),
306-
&krate,
307-
*ppm,
308-
compiler.output_file().as_ref().map(|p| &**p),
309-
);
312+
}
313+
return early_exit();
310314
}
311-
return sess.compile_status();
312-
}
313315

314-
if callbacks.after_parsing(compiler) == Compilation::Stop {
315-
return sess.compile_status();
316-
}
316+
if callbacks.after_parsing(compiler) == Compilation::Stop {
317+
return early_exit();
318+
}
317319

318-
if sess.opts.debugging_opts.parse_only ||
319-
sess.opts.debugging_opts.show_span.is_some() ||
320-
sess.opts.debugging_opts.ast_json_noexpand {
321-
return sess.compile_status();
322-
}
320+
if sess.opts.debugging_opts.parse_only ||
321+
sess.opts.debugging_opts.show_span.is_some() ||
322+
sess.opts.debugging_opts.ast_json_noexpand {
323+
return early_exit();
324+
}
323325

324-
{
325-
let (_, lint_store) = &*compiler.register_plugins()?.peek();
326+
{
327+
let (_, lint_store) = &*queries.register_plugins()?.peek();
326328

327-
// Lint plugins are registered; now we can process command line flags.
328-
if sess.opts.describe_lints {
329-
describe_lints(&sess, &lint_store, true);
330-
return sess.compile_status();
329+
// Lint plugins are registered; now we can process command line flags.
330+
if sess.opts.describe_lints {
331+
describe_lints(&sess, &lint_store, true);
332+
return early_exit();
333+
}
331334
}
332-
}
333335

334-
compiler.expansion()?;
335-
if callbacks.after_expansion(compiler) == Compilation::Stop {
336-
return sess.compile_status();
337-
}
336+
queries.expansion()?;
337+
if callbacks.after_expansion(compiler) == Compilation::Stop {
338+
return early_exit();
339+
}
338340

339-
compiler.prepare_outputs()?;
341+
queries.prepare_outputs()?;
340342

341-
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
342-
&& sess.opts.output_types.len() == 1
343-
{
344-
return sess.compile_status();
345-
}
343+
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
344+
&& sess.opts.output_types.len() == 1
345+
{
346+
return early_exit();
347+
}
346348

347-
compiler.global_ctxt()?;
349+
queries.global_ctxt()?;
348350

349-
if sess.opts.debugging_opts.no_analysis ||
350-
sess.opts.debugging_opts.ast_json {
351-
return sess.compile_status();
352-
}
351+
if sess.opts.debugging_opts.no_analysis ||
352+
sess.opts.debugging_opts.ast_json {
353+
return early_exit();
354+
}
353355

354-
if sess.opts.debugging_opts.save_analysis {
355-
let expanded_crate = &compiler.expansion()?.peek().0;
356-
let crate_name = compiler.crate_name()?.peek().clone();
357-
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
358-
let result = tcx.analysis(LOCAL_CRATE);
359-
360-
time(sess, "save analysis", || {
361-
save::process_crate(
362-
tcx,
363-
&expanded_crate,
364-
&crate_name,
365-
&compiler.input(),
366-
None,
367-
DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name)
368-
)
369-
});
370-
371-
result
372-
// AST will be dropped *after* the `after_analysis` callback
373-
// (needed by the RLS)
374-
})?;
375-
} else {
376-
// Drop AST after creating GlobalCtxt to free memory
377-
mem::drop(compiler.expansion()?.take());
378-
}
356+
if sess.opts.debugging_opts.save_analysis {
357+
let expanded_crate = &queries.expansion()?.peek().0;
358+
let crate_name = queries.crate_name()?.peek().clone();
359+
queries.global_ctxt()?.peek_mut().enter(|tcx| {
360+
let result = tcx.analysis(LOCAL_CRATE);
361+
362+
time(sess, "save analysis", || {
363+
save::process_crate(
364+
tcx,
365+
&expanded_crate,
366+
&crate_name,
367+
&compiler.input(),
368+
None,
369+
DumpHandler::new(
370+
compiler.output_dir().as_ref().map(|p| &**p), &crate_name
371+
)
372+
)
373+
});
379374

380-
compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
375+
result
376+
// AST will be dropped *after* the `after_analysis` callback
377+
// (needed by the RLS)
378+
})?;
379+
} else {
380+
// Drop AST after creating GlobalCtxt to free memory
381+
mem::drop(queries.expansion()?.take());
382+
}
381383

382-
if callbacks.after_analysis(compiler) == Compilation::Stop {
383-
return sess.compile_status();
384-
}
384+
queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
385385

386-
if sess.opts.debugging_opts.save_analysis {
387-
mem::drop(compiler.expansion()?.take());
388-
}
386+
if callbacks.after_analysis(compiler) == Compilation::Stop {
387+
return early_exit();
388+
}
389389

390-
compiler.ongoing_codegen()?;
390+
if sess.opts.debugging_opts.save_analysis {
391+
mem::drop(queries.expansion()?.take());
392+
}
391393

392-
// Drop GlobalCtxt after starting codegen to free memory
393-
mem::drop(compiler.global_ctxt()?.take());
394+
queries.ongoing_codegen()?;
394395

395-
if sess.opts.debugging_opts.print_type_sizes {
396-
sess.code_stats.print_type_sizes();
397-
}
396+
if sess.opts.debugging_opts.print_type_sizes {
397+
sess.code_stats.print_type_sizes();
398+
}
398399

399-
compiler.link()?;
400+
let linker = queries.linker()?;
401+
Ok(Some(linker))
402+
})?;
403+
404+
if let Some(linker) = linker {
405+
linker.link()?
406+
}
400407

401408
if sess.opts.debugging_opts.perf_stats {
402409
sess.print_perf_stats();

‎src/librustc_interface/interface.rs‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::queries::Queries;
21
use crate::util;
32
pub use crate::passes::BoxedResolver;
43

@@ -36,7 +35,6 @@ pub struct Compiler {
3635
pub(crate) input_path: Option<PathBuf>,
3736
pub(crate) output_dir: Option<PathBuf>,
3837
pub(crate) output_file: Option<PathBuf>,
39-
pub(crate) queries: Queries,
4038
pub(crate) crate_name: Option<String>,
4139
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
4240
pub(crate) override_queries:
@@ -169,7 +167,6 @@ pub fn run_compiler_in_existing_thread_pool<R>(
169167
input_path: config.input_path,
170168
output_dir: config.output_dir,
171169
output_file: config.output_file,
172-
queries: Default::default(),
173170
crate_name: config.crate_name,
174171
register_lints: config.register_lints,
175172
override_queries: config.override_queries,

‎src/librustc_interface/passes.rs‎

Lines changed: 52 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::util;
33
use crate::proc_macro_decls;
44

55
use log::{info, warn, log_enabled};
6+
use rustc::arena::Arena;
67
use rustc::dep_graph::DepGraph;
78
use rustc::hir;
89
use rustc::hir::lowering::lower_crate;
@@ -22,7 +23,7 @@ use rustc_codegen_ssa::back::link::emit_metadata;
2223
use rustc_codegen_utils::codegen_backend::CodegenBackend;
2324
use rustc_codegen_utils::link::filename_for_metadata;
2425
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
25-
use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
26+
use rustc_data_structures::sync::{Lrc, Once, ParallelIterator, par_iter, WorkerLocal};
2627
use rustc_errors::PResult;
2728
use rustc_incremental;
2829
use rustc_mir as mir;
@@ -739,93 +740,77 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) {
739740
rustc_codegen_ssa::provide_extern(providers);
740741
}
741742

742-
declare_box_region_type!(
743-
pub BoxedGlobalCtxt,
744-
for('tcx),
745-
(&'tcx GlobalCtxt<'tcx>) -> ((), ())
746-
);
743+
pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>);
747744

748-
impl BoxedGlobalCtxt {
745+
impl<'tcx> QueryContext<'tcx> {
749746
pub fn enter<F, R>(&mut self, f: F) -> R
750747
where
751-
F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
748+
F: FnOnce(TyCtxt<'tcx>) -> R,
752749
{
753-
self.access(|gcx| ty::tls::enter_global(gcx, |tcx| f(tcx)))
750+
ty::tls::enter_global(self.0, |tcx| f(tcx))
751+
}
752+
753+
pub fn print_stats(&self) {
754+
self.0.queries.print_stats()
754755
}
755756
}
756757

757-
pub fn create_global_ctxt(
758-
compiler: &Compiler,
758+
pub fn create_global_ctxt<'tcx>(
759+
compiler: &'tcx Compiler,
759760
lint_store: Lrc<lint::LintStore>,
760-
mut hir_forest: hir::map::Forest,
761+
hir_forest: &'tcx hir::map::Forest,
761762
mut resolver_outputs: ResolverOutputs,
762763
outputs: OutputFilenames,
763764
crate_name: &str,
764-
) -> BoxedGlobalCtxt {
765-
let sess = compiler.session().clone();
766-
let codegen_backend = compiler.codegen_backend().clone();
767-
let crate_name = crate_name.to_string();
765+
global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
766+
all_arenas: &'tcx AllArenas,
767+
arena: &'tcx WorkerLocal<Arena<'tcx>>,
768+
) -> QueryContext<'tcx> {
769+
let sess = &compiler.session();
768770
let defs = mem::take(&mut resolver_outputs.definitions);
769-
let override_queries = compiler.override_queries;
770-
771-
let ((), result) = BoxedGlobalCtxt::new(static move || {
772-
let sess = &*sess;
773-
774-
let global_ctxt: Option<GlobalCtxt<'_>>;
775-
let arenas = AllArenas::new();
776-
777-
// Construct the HIR map.
778-
let hir_map = time(sess, "indexing HIR", || {
779-
hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs)
780-
});
781-
782-
let query_result_on_disk_cache = time(sess, "load query result cache", || {
783-
rustc_incremental::load_query_result_cache(sess)
784-
});
785771

786-
let mut local_providers = ty::query::Providers::default();
787-
default_provide(&mut local_providers);
788-
codegen_backend.provide(&mut local_providers);
772+
// Construct the HIR map.
773+
let hir_map = time(sess, "indexing HIR", || {
774+
hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs)
775+
});
789776

790-
let mut extern_providers = local_providers;
791-
default_provide_extern(&mut extern_providers);
792-
codegen_backend.provide_extern(&mut extern_providers);
777+
let query_result_on_disk_cache = time(sess, "load query result cache", || {
778+
rustc_incremental::load_query_result_cache(sess)
779+
});
793780

794-
if let Some(callback) = override_queries {
795-
callback(sess, &mut local_providers, &mut extern_providers);
796-
}
781+
let codegen_backend = compiler.codegen_backend();
782+
let mut local_providers = ty::query::Providers::default();
783+
default_provide(&mut local_providers);
784+
codegen_backend.provide(&mut local_providers);
797785

798-
let gcx = TyCtxt::create_global_ctxt(
799-
sess,
800-
lint_store,
801-
local_providers,
802-
extern_providers,
803-
&arenas,
804-
resolver_outputs,
805-
hir_map,
806-
query_result_on_disk_cache,
807-
&crate_name,
808-
&outputs
809-
);
786+
let mut extern_providers = local_providers;
787+
default_provide_extern(&mut extern_providers);
788+
codegen_backend.provide_extern(&mut extern_providers);
810789

811-
global_ctxt = Some(gcx);
812-
let gcx = global_ctxt.as_ref().unwrap();
813-
814-
ty::tls::enter_global(gcx, |tcx| {
815-
// Do some initialization of the DepGraph that can only be done with the
816-
// tcx available.
817-
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
818-
});
790+
if let Some(callback) = compiler.override_queries {
791+
callback(sess, &mut local_providers, &mut extern_providers);
792+
}
819793

820-
yield BoxedGlobalCtxt::initial_yield(());
821-
box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx));
794+
let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt(
795+
sess,
796+
lint_store,
797+
local_providers,
798+
extern_providers,
799+
&all_arenas,
800+
arena,
801+
resolver_outputs,
802+
hir_map,
803+
query_result_on_disk_cache,
804+
&crate_name,
805+
&outputs
806+
));
822807

823-
if sess.opts.debugging_opts.query_stats {
824-
gcx.queries.print_stats();
825-
}
808+
// Do some initialization of the DepGraph that can only be done with the tcx available.
809+
ty::tls::enter_global(&gcx, |tcx| {
810+
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
826811
});
827812

828-
result
813+
QueryContext(gcx)
829814
}
830815

831816
/// Runs the resolution, type-checking, region checking and other

‎src/librustc_interface/queries.rs‎

Lines changed: 142 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
use crate::interface::{Compiler, Result};
2-
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};
2+
use crate::passes::{self, BoxedResolver, QueryContext};
33

44
use rustc_incremental::DepGraphFuture;
5-
use rustc_data_structures::sync::Lrc;
5+
use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
6+
use rustc_codegen_utils::codegen_backend::CodegenBackend;
67
use rustc::session::config::{OutputFilenames, OutputType};
78
use rustc::util::common::{time, ErrorReported};
9+
use rustc::arena::Arena;
810
use rustc::hir;
911
use rustc::lint;
1012
use rustc::session::Session;
1113
use rustc::lint::LintStore;
1214
use rustc::hir::def_id::LOCAL_CRATE;
1315
use rustc::ty::steal::Steal;
14-
use rustc::ty::ResolverOutputs;
16+
use rustc::ty::{AllArenas, ResolverOutputs, GlobalCtxt};
1517
use rustc::dep_graph::DepGraph;
1618
use std::cell::{Ref, RefMut, RefCell};
1719
use std::rc::Rc;
@@ -44,13 +46,6 @@ impl<T> Query<T> {
4446
.unwrap()
4547
}
4648

47-
/// Returns a stolen query result. Panics if there's already a result.
48-
pub fn give(&self, value: T) {
49-
let mut result = self.result.borrow_mut();
50-
assert!(result.is_none(), "a result already exists");
51-
*result = Some(Ok(value));
52-
}
53-
5449
/// Borrows the query result using the RefCell. Panics if the result is stolen.
5550
pub fn peek(&self) -> Ref<'_, T> {
5651
Ref::map(self.result.borrow(), |r| {
@@ -74,24 +69,54 @@ impl<T> Default for Query<T> {
7469
}
7570
}
7671

77-
#[derive(Default)]
78-
pub(crate) struct Queries {
72+
pub struct Queries<'tcx> {
73+
compiler: &'tcx Compiler,
74+
gcx: Once<GlobalCtxt<'tcx>>,
75+
76+
all_arenas: AllArenas,
77+
arena: WorkerLocal<Arena<'tcx>>,
78+
7979
dep_graph_future: Query<Option<DepGraphFuture>>,
8080
parse: Query<ast::Crate>,
8181
crate_name: Query<String>,
8282
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
8383
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
8484
dep_graph: Query<DepGraph>,
85-
lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
85+
lower_to_hir: Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>,
8686
prepare_outputs: Query<OutputFilenames>,
87-
global_ctxt: Query<BoxedGlobalCtxt>,
87+
global_ctxt: Query<QueryContext<'tcx>>,
8888
ongoing_codegen: Query<Box<dyn Any>>,
89-
link: Query<()>,
9089
}
9190

92-
impl Compiler {
91+
impl<'tcx> Queries<'tcx> {
92+
pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
93+
Queries {
94+
compiler,
95+
gcx: Once::new(),
96+
all_arenas: AllArenas::new(),
97+
arena: WorkerLocal::new(|_| Arena::default()),
98+
dep_graph_future: Default::default(),
99+
parse: Default::default(),
100+
crate_name: Default::default(),
101+
register_plugins: Default::default(),
102+
expansion: Default::default(),
103+
dep_graph: Default::default(),
104+
lower_to_hir: Default::default(),
105+
prepare_outputs: Default::default(),
106+
global_ctxt: Default::default(),
107+
ongoing_codegen: Default::default(),
108+
}
109+
}
110+
111+
fn session(&self) -> &Lrc<Session> {
112+
&self.compiler.sess
113+
}
114+
fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
115+
&self.compiler.codegen_backend()
116+
}
117+
93118
pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
94-
self.queries.dep_graph_future.compute(|| {
119+
self.dep_graph_future.compute(|| {
95120
Ok(if self.session().opts.build_dep_graph() {
96121
Some(rustc_incremental::load_dep_graph(self.session()))
97122
} else {
@@ -101,8 +126,8 @@ impl Compiler {
101126
}
102127

103128
pub fn parse(&self) -> Result<&Query<ast::Crate>> {
104-
self.queries.parse.compute(|| {
105-
passes::parse(self.session(), &self.input).map_err(
129+
self.parse.compute(|| {
130+
passes::parse(self.session(), &self.compiler.input).map_err(
106131
|mut parse_error| {
107132
parse_error.emit();
108133
ErrorReported
@@ -112,15 +137,15 @@ impl Compiler {
112137
}
113138

114139
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
115-
self.queries.register_plugins.compute(|| {
140+
self.register_plugins.compute(|| {
116141
let crate_name = self.crate_name()?.peek().clone();
117142
let krate = self.parse()?.take();
118143

119144
let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
120145
let result = passes::register_plugins(
121146
self.session(),
122147
&*self.codegen_backend().metadata_loader(),
123-
self.register_lints
148+
self.compiler.register_lints
124149
.as_ref()
125150
.map(|p| &**p)
126151
.unwrap_or_else(|| empty),
@@ -140,16 +165,16 @@ impl Compiler {
140165
}
141166

142167
pub fn crate_name(&self) -> Result<&Query<String>> {
143-
self.queries.crate_name.compute(|| {
144-
Ok(match self.crate_name {
168+
self.crate_name.compute(|| {
169+
Ok(match self.compiler.crate_name {
145170
Some(ref crate_name) => crate_name.clone(),
146171
None => {
147172
let parse_result = self.parse()?;
148173
let krate = parse_result.peek();
149174
rustc_codegen_utils::link::find_crate_name(
150175
Some(self.session()),
151176
&krate.attrs,
152-
&self.input
177+
&self.compiler.input
153178
)
154179
}
155180
})
@@ -159,11 +184,11 @@ impl Compiler {
159184
pub fn expansion(
160185
&self
161186
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
162-
self.queries.expansion.compute(|| {
187+
self.expansion.compute(|| {
163188
let crate_name = self.crate_name()?.peek().clone();
164189
let (krate, lint_store) = self.register_plugins()?.take();
165190
passes::configure_and_expand(
166-
self.sess.clone(),
191+
self.session().clone(),
167192
lint_store.clone(),
168193
self.codegen_backend().metadata_loader(),
169194
krate,
@@ -175,7 +200,7 @@ impl Compiler {
175200
}
176201

177202
pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
178-
self.queries.dep_graph.compute(|| {
203+
self.dep_graph.compute(|| {
179204
Ok(match self.dep_graph_future()?.take() {
180205
None => DepGraph::new_disabled(),
181206
Some(future) => {
@@ -192,57 +217,63 @@ impl Compiler {
192217
}
193218

194219
pub fn lower_to_hir(
195-
&self,
196-
) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
197-
self.queries.lower_to_hir.compute(|| {
220+
&'tcx self,
221+
) -> Result<&Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>> {
222+
self.lower_to_hir.compute(|| {
198223
let expansion_result = self.expansion()?;
199224
let peeked = expansion_result.peek();
200225
let krate = &peeked.0;
201226
let resolver = peeked.1.steal();
202227
let lint_store = &peeked.2;
203-
let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
228+
let hir = resolver.borrow_mut().access(|resolver| {
204229
passes::lower_to_hir(
205230
self.session(),
206231
lint_store,
207232
resolver,
208233
&*self.dep_graph()?.peek(),
209234
&krate
210235
)
211-
})?);
236+
})?;
237+
let hir = self.arena.alloc(hir);
212238
Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
213239
})
214240
}
215241

216242
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
217-
self.queries.prepare_outputs.compute(|| {
243+
self.prepare_outputs.compute(|| {
218244
let expansion_result = self.expansion()?;
219245
let (krate, boxed_resolver, _) = &*expansion_result.peek();
220246
let crate_name = self.crate_name()?;
221247
let crate_name = crate_name.peek();
222-
passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name)
248+
passes::prepare_outputs(
249+
self.session(), self.compiler, &krate, &boxed_resolver, &crate_name
250+
)
223251
})
224252
}
225253

226-
pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
227-
self.queries.global_ctxt.compute(|| {
254+
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
255+
self.global_ctxt.compute(|| {
228256
let crate_name = self.crate_name()?.peek().clone();
229257
let outputs = self.prepare_outputs()?.peek().clone();
230258
let lint_store = self.expansion()?.peek().2.clone();
231-
let hir = self.lower_to_hir()?;
232-
let hir = hir.peek();
233-
let (hir_forest, resolver_outputs) = &*hir;
259+
let hir = self.lower_to_hir()?.peek();
260+
let (ref hir_forest, ref resolver_outputs) = &*hir;
234261
Ok(passes::create_global_ctxt(
235-
self,
262+
self.compiler,
236263
lint_store,
237-
hir_forest.steal(),
264+
hir_forest,
238265
resolver_outputs.steal(),
239266
outputs,
240-
&crate_name))
267+
&crate_name,
268+
&self.gcx,
269+
&self.all_arenas,
270+
&self.arena,
271+
))
241272
})
242273
}
243274

244-
pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
245-
self.queries.ongoing_codegen.compute(|| {
275+
pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> {
276+
self.ongoing_codegen.compute(|| {
246277
let outputs = self.prepare_outputs()?;
247278
self.global_ctxt()?.peek_mut().enter(|tcx| {
248279
tcx.analysis(LOCAL_CRATE).ok();
@@ -259,47 +290,89 @@ impl Compiler {
259290
})
260291
}
261292

262-
pub fn link(&self) -> Result<&Query<()>> {
263-
self.queries.link.compute(|| {
264-
let sess = self.session();
265-
266-
let ongoing_codegen = self.ongoing_codegen()?.take();
293+
pub fn linker(&'tcx self) -> Result<Linker> {
294+
let dep_graph = self.dep_graph()?;
295+
let prepare_outputs = self.prepare_outputs()?;
296+
let ongoing_codegen = self.ongoing_codegen()?;
267297

268-
self.codegen_backend().join_codegen_and_link(
269-
ongoing_codegen,
270-
sess,
271-
&*self.dep_graph()?.peek(),
272-
&*self.prepare_outputs()?.peek(),
273-
).map_err(|_| ErrorReported)?;
298+
let sess = self.session().clone();
299+
let codegen_backend = self.codegen_backend().clone();
274300

275-
Ok(())
301+
Ok(Linker {
302+
sess,
303+
dep_graph: dep_graph.peek().clone(),
304+
prepare_outputs: prepare_outputs.take(),
305+
ongoing_codegen: ongoing_codegen.take(),
306+
codegen_backend,
276307
})
277308
}
309+
}
310+
311+
pub struct Linker {
312+
sess: Lrc<Session>,
313+
dep_graph: DepGraph,
314+
prepare_outputs: OutputFilenames,
315+
ongoing_codegen: Box<dyn Any>,
316+
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
317+
}
318+
319+
impl Linker {
320+
pub fn link(self) -> Result<()> {
321+
self.codegen_backend.join_codegen_and_link(
322+
self.ongoing_codegen,
323+
&self.sess,
324+
&self.dep_graph,
325+
&self.prepare_outputs,
326+
).map_err(|_| ErrorReported)
327+
}
328+
}
329+
330+
impl Compiler {
331+
pub fn enter<F, T>(&self, f: F) -> T
332+
where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T
333+
{
334+
let queries = Queries::new(&self);
335+
let ret = f(&queries);
336+
337+
if self.session().opts.debugging_opts.query_stats {
338+
if let Ok(gcx) = queries.global_ctxt() {
339+
gcx.peek().print_stats();
340+
}
341+
}
342+
343+
ret
344+
}
278345

279346
// This method is different to all the other methods in `Compiler` because
280347
// it lacks a `Queries` entry. It's also not currently used. It does serve
281348
// as an example of how `Compiler` can be used, with additional steps added
282349
// between some passes. And see `rustc_driver::run_compiler` for a more
283350
// complex example.
284351
pub fn compile(&self) -> Result<()> {
285-
self.prepare_outputs()?;
352+
let linker = self.enter(|queries| {
353+
queries.prepare_outputs()?;
286354

287-
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
288-
&& self.session().opts.output_types.len() == 1
289-
{
290-
return Ok(())
291-
}
355+
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
356+
&& self.session().opts.output_types.len() == 1
357+
{
358+
return Ok(None)
359+
}
360+
361+
queries.global_ctxt()?;
292362

293-
self.global_ctxt()?;
363+
// Drop AST after creating GlobalCtxt to free memory.
364+
mem::drop(queries.expansion()?.take());
294365

295-
// Drop AST after creating GlobalCtxt to free memory.
296-
mem::drop(self.expansion()?.take());
366+
queries.ongoing_codegen()?;
297367

298-
self.ongoing_codegen()?;
368+
let linker = queries.linker()?;
369+
Ok(Some(linker))
370+
})?;
299371

300-
// Drop GlobalCtxt after starting codegen to free memory.
301-
mem::drop(self.global_ctxt()?.take());
372+
if let Some(linker) = linker {
373+
linker.link()?
374+
}
302375

303-
self.link().map(|_| ())
376+
Ok(())
304377
}
305378
}

‎src/librustdoc/core.rs‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,25 +343,26 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
343343
registry: rustc_driver::diagnostics_registry(),
344344
};
345345

346-
interface::run_compiler_in_existing_thread_pool(config, |compiler| {
346+
interface::run_compiler_in_existing_thread_pool(config, |compiler| compiler.enter(|queries| {
347347
let sess = compiler.session();
348348

349349
// We need to hold on to the complete resolver, so we cause everything to be
350350
// cloned for the analysis passes to use. Suboptimal, but necessary in the
351351
// current architecture.
352352
let resolver = {
353-
let parts = abort_on_err(compiler.expansion(), sess).peek();
353+
let parts = abort_on_err(queries.expansion(), sess).peek();
354354
let resolver = parts.1.borrow();
355355

356356
// Before we actually clone it, let's force all the extern'd crates to
357357
// actually be loaded, just in case they're only referred to inside
358358
// intra-doc-links
359359
resolver.borrow_mut().access(|resolver| {
360360
for extern_name in &extern_names {
361-
resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID)
362-
.unwrap_or_else(
363-
|()| panic!("Unable to resolve external crate {}", extern_name)
364-
);
361+
resolver.resolve_str_path_error(
362+
DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID
363+
).unwrap_or_else(
364+
|()| panic!("Unable to resolve external crate {}", extern_name)
365+
);
365366
}
366367
});
367368

@@ -373,7 +374,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
373374
sess.fatal("Compilation failed, aborting rustdoc");
374375
}
375376

376-
let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take();
377+
let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
377378

378379
global_ctxt.enter(|tcx| {
379380
tcx.analysis(LOCAL_CRATE).ok();
@@ -447,8 +448,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
447448
},
448449
sym::plugins => {
449450
report_deprecated_attr("plugins = \"...\"", diag);
450-
eprintln!("WARNING: `#![doc(plugins = \"...\")]` no longer functions; \
451-
see CVE-2018-1000622");
451+
eprintln!("WARNING: `#![doc(plugins = \"...\")]` \
452+
no longer functions; see CVE-2018-1000622");
452453
continue
453454
},
454455
_ => continue,
@@ -486,7 +487,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
486487

487488
(krate, ctxt.renderinfo.into_inner(), render_options)
488489
})
489-
})
490+
}))
490491
}
491492

492493
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter

‎src/librustdoc/test.rs‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,14 @@ pub fn run(options: Options) -> i32 {
8585
let mut test_args = options.test_args.clone();
8686
let display_warnings = options.display_warnings;
8787

88-
let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> {
89-
let lower_to_hir = compiler.lower_to_hir()?;
88+
let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| {
89+
let lower_to_hir = queries.lower_to_hir()?;
9090

91-
let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate());
91+
let mut opts = scrape_test_config(lower_to_hir.peek().0.krate());
9292
opts.display_warnings |= options.display_warnings;
9393
let enable_per_target_ignores = options.enable_per_target_ignores;
9494
let mut collector = Collector::new(
95-
compiler.crate_name()?.peek().to_string(),
95+
queries.crate_name()?.peek().to_string(),
9696
options,
9797
false,
9898
opts,
@@ -101,7 +101,8 @@ pub fn run(options: Options) -> i32 {
101101
enable_per_target_ignores,
102102
);
103103

104-
let mut global_ctxt = compiler.global_ctxt()?.take();
104+
let mut global_ctxt = queries.global_ctxt()?.take();
105+
105106
global_ctxt.enter(|tcx| {
106107
let krate = tcx.hir().krate();
107108
let mut hir_collector = HirCollector {
@@ -116,8 +117,9 @@ pub fn run(options: Options) -> i32 {
116117
});
117118
});
118119

119-
Ok(collector.tests)
120-
}).expect("compiler aborted in rustdoc!");
120+
let ret : Result<_, ErrorReported> = Ok(collector.tests);
121+
ret
122+
})).expect("compiler aborted in rustdoc!");
121123

122124
test_args.insert(0, "rustdoctest".to_string());
123125

‎src/test/run-make-fulldeps/issue-19371/foo.rs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
6666

6767
interface::run_compiler(config, |compiler| {
6868
// This runs all the passes prior to linking, too.
69-
compiler.link().ok();
69+
let linker = compiler.enter(|queries| {
70+
queries.linker()
71+
});
72+
if let Ok(linker) = linker {
73+
linker.link();
74+
}
7075
});
7176
}

0 commit comments

Comments
 (0)
Please sign in to comment.