diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 9b13a910c6174..193b04eabb3fb 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -93,6 +93,7 @@ macro_rules! arena_types { rustc::hir::def_id::CrateNum > >, + [few] hir_forest: rustc::hir::map::Forest, [few] diagnostic_items: rustc_data_structures::fx::FxHashMap< syntax::symbol::Symbol, rustc::hir::def_id::DefId, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index fc754c5e675e6..5bf5a93ad0102 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -200,7 +200,7 @@ pub struct Map<'hir> { map: HirEntryMap<'hir>, - definitions: &'hir Definitions, + definitions: Definitions, /// The reverse mapping of `node_to_hir_id`. hir_to_node_id: FxHashMap, @@ -267,8 +267,8 @@ impl<'hir> Map<'hir> { } #[inline] - pub fn definitions(&self) -> &'hir Definitions { - self.definitions + pub fn definitions(&self) -> &Definitions { + &self.definitions } pub fn def_key(&self, def_id: DefId) -> DefKey { @@ -1251,7 +1251,7 @@ impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } pub fn map_crate<'hir>(sess: &crate::session::Session, cstore: &CrateStoreDyn, forest: &'hir Forest, - definitions: &'hir Definitions) + definitions: Definitions) -> Map<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); @@ -1260,7 +1260,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); let (map, crate_hash) = { - let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore); + let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore); let mut collector = NodeCollector::root(sess, &forest.krate, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 954565811694f..3c1cfa3f79f37 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -995,7 +995,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> { } pub struct GlobalCtxt<'tcx> { - pub arena: WorkerLocal>, + pub arena: &'tcx WorkerLocal>, interners: CtxtInterners<'tcx>, @@ -1170,6 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> { local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, + arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, @@ -1225,7 +1226,7 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, cstore, - arena: WorkerLocal::new(|_| Arena::default()), + arena, interners, dep_graph, prof: s.prof.clone(), diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 13829b842fd5f..c945de8f1e1dc 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -283,120 +283,127 @@ pub fn run_compiler( return sess.compile_status(); } - compiler.parse()?; - - if let Some(ppm) = &sess.opts.pretty { - if ppm.needs_ast_map() { - compiler.global_ctxt()?.peek_mut().enter(|tcx| { - let expanded_crate = compiler.expansion()?.take().0; - pretty::print_after_hir_lowering( - tcx, - compiler.input(), - &expanded_crate, + let linker = compiler.enter(|queries| { + let early_exit = || sess.compile_status().map(|_| None); + queries.parse()?; + + if let Some(ppm) = &sess.opts.pretty { + if ppm.needs_ast_map() { + queries.global_ctxt()?.peek_mut().enter(|tcx| { + let expanded_crate = queries.expansion()?.take().0; + pretty::print_after_hir_lowering( + tcx, + compiler.input(), + &expanded_crate, + *ppm, + compiler.output_file().as_ref().map(|p| &**p), + ); + Ok(()) + })?; + } else { + let krate = queries.parse()?.take(); + pretty::print_after_parsing( + sess, + &compiler.input(), + &krate, *ppm, compiler.output_file().as_ref().map(|p| &**p), ); - Ok(()) - })?; - } else { - let krate = compiler.parse()?.take(); - pretty::print_after_parsing( - sess, - &compiler.input(), - &krate, - *ppm, - compiler.output_file().as_ref().map(|p| &**p), - ); + } + return early_exit(); } - return sess.compile_status(); - } - if callbacks.after_parsing(compiler) == Compilation::Stop { - return sess.compile_status(); - } + if callbacks.after_parsing(compiler) == Compilation::Stop { + return early_exit(); + } - if sess.opts.debugging_opts.parse_only || - sess.opts.debugging_opts.show_span.is_some() || - sess.opts.debugging_opts.ast_json_noexpand { - return sess.compile_status(); - } + if sess.opts.debugging_opts.parse_only || + sess.opts.debugging_opts.show_span.is_some() || + sess.opts.debugging_opts.ast_json_noexpand { + return early_exit(); + } - { - let (_, lint_store) = &*compiler.register_plugins()?.peek(); + { + let (_, lint_store) = &*queries.register_plugins()?.peek(); - // Lint plugins are registered; now we can process command line flags. - if sess.opts.describe_lints { - describe_lints(&sess, &lint_store, true); - return sess.compile_status(); + // Lint plugins are registered; now we can process command line flags. + if sess.opts.describe_lints { + describe_lints(&sess, &lint_store, true); + return early_exit(); + } } - } - compiler.expansion()?; - if callbacks.after_expansion(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.expansion()?; + if callbacks.after_expansion(compiler) == Compilation::Stop { + return early_exit(); + } - compiler.prepare_outputs()?; + queries.prepare_outputs()?; - if sess.opts.output_types.contains_key(&OutputType::DepInfo) - && sess.opts.output_types.len() == 1 - { - return sess.compile_status(); - } + if sess.opts.output_types.contains_key(&OutputType::DepInfo) + && sess.opts.output_types.len() == 1 + { + return early_exit(); + } - compiler.global_ctxt()?; + queries.global_ctxt()?; - if sess.opts.debugging_opts.no_analysis || - sess.opts.debugging_opts.ast_json { - return sess.compile_status(); - } + if sess.opts.debugging_opts.no_analysis || + sess.opts.debugging_opts.ast_json { + return early_exit(); + } - if sess.opts.debugging_opts.save_analysis { - let expanded_crate = &compiler.expansion()?.peek().0; - let crate_name = compiler.crate_name()?.peek().clone(); - compiler.global_ctxt()?.peek_mut().enter(|tcx| { - let result = tcx.analysis(LOCAL_CRATE); - - time(sess, "save analysis", || { - save::process_crate( - tcx, - &expanded_crate, - &crate_name, - &compiler.input(), - None, - DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name) - ) - }); - - result - // AST will be dropped *after* the `after_analysis` callback - // (needed by the RLS) - })?; - } else { - // Drop AST after creating GlobalCtxt to free memory - mem::drop(compiler.expansion()?.take()); - } + if sess.opts.debugging_opts.save_analysis { + let expanded_crate = &queries.expansion()?.peek().0; + let crate_name = queries.crate_name()?.peek().clone(); + queries.global_ctxt()?.peek_mut().enter(|tcx| { + let result = tcx.analysis(LOCAL_CRATE); + + time(sess, "save analysis", || { + save::process_crate( + tcx, + &expanded_crate, + &crate_name, + &compiler.input(), + None, + DumpHandler::new( + compiler.output_dir().as_ref().map(|p| &**p), &crate_name + ) + ) + }); - compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; + result + // AST will be dropped *after* the `after_analysis` callback + // (needed by the RLS) + })?; + } else { + // Drop AST after creating GlobalCtxt to free memory + mem::drop(queries.expansion()?.take()); + } - if callbacks.after_analysis(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; - if sess.opts.debugging_opts.save_analysis { - mem::drop(compiler.expansion()?.take()); - } + if callbacks.after_analysis(compiler) == Compilation::Stop { + return early_exit(); + } - compiler.ongoing_codegen()?; + if sess.opts.debugging_opts.save_analysis { + mem::drop(queries.expansion()?.take()); + } - // Drop GlobalCtxt after starting codegen to free memory - mem::drop(compiler.global_ctxt()?.take()); + queries.ongoing_codegen()?; - if sess.opts.debugging_opts.print_type_sizes { - sess.code_stats.print_type_sizes(); - } + if sess.opts.debugging_opts.print_type_sizes { + sess.code_stats.print_type_sizes(); + } - compiler.link()?; + let linker = queries.linker()?; + Ok(Some(linker)) + })?; + + if let Some(linker) = linker { + linker.link()? + } if sess.opts.debugging_opts.perf_stats { sess.print_perf_stats(); diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 70ed4aad7b4aa..beb2465bd4a1a 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -1,4 +1,3 @@ -use crate::queries::Queries; use crate::util; pub use crate::passes::BoxedResolver; @@ -36,7 +35,6 @@ pub struct Compiler { pub(crate) input_path: Option, pub(crate) output_dir: Option, pub(crate) output_file: Option, - pub(crate) queries: Queries, pub(crate) crate_name: Option, pub(crate) register_lints: Option>, pub(crate) override_queries: @@ -169,7 +167,6 @@ pub fn run_compiler_in_existing_thread_pool( input_path: config.input_path, output_dir: config.output_dir, output_file: config.output_file, - queries: Default::default(), crate_name: config.crate_name, register_lints: config.register_lints, override_queries: config.override_queries, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a745d63426b7a..1df84ce0b7394 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -3,6 +3,7 @@ use crate::util; use crate::proc_macro_decls; use log::{info, warn, log_enabled}; +use rustc::arena::Arena; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::lowering::lower_crate; @@ -22,7 +23,7 @@ use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::link::filename_for_metadata; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; -use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter}; +use rustc_data_structures::sync::{Lrc, Once, ParallelIterator, par_iter, WorkerLocal}; use rustc_errors::PResult; use rustc_incremental; use rustc_metadata::cstore; @@ -740,93 +741,77 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { rustc_codegen_ssa::provide_extern(providers); } -declare_box_region_type!( - pub BoxedGlobalCtxt, - for('tcx), - (&'tcx GlobalCtxt<'tcx>) -> ((), ()) -); +pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>); -impl BoxedGlobalCtxt { +impl<'tcx> QueryContext<'tcx> { pub fn enter(&mut self, f: F) -> R where - F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R, + F: FnOnce(TyCtxt<'tcx>) -> R, { - self.access(|gcx| ty::tls::enter_global(gcx, |tcx| f(tcx))) + ty::tls::enter_global(self.0, |tcx| f(tcx)) + } + + pub fn print_stats(&self) { + self.0.queries.print_stats() } } -pub fn create_global_ctxt( - compiler: &Compiler, +pub fn create_global_ctxt<'tcx>( + compiler: &'tcx Compiler, lint_store: Lrc, - mut hir_forest: hir::map::Forest, + hir_forest: &'tcx hir::map::Forest, mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, -) -> BoxedGlobalCtxt { - let sess = compiler.session().clone(); - let codegen_backend = compiler.codegen_backend().clone(); - let crate_name = crate_name.to_string(); + global_ctxt: &'tcx Once>, + all_arenas: &'tcx AllArenas, + arena: &'tcx WorkerLocal>, +) -> QueryContext<'tcx> { + let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); - let override_queries = compiler.override_queries; - - let ((), result) = BoxedGlobalCtxt::new(static move || { - let sess = &*sess; - - let global_ctxt: Option>; - let arenas = AllArenas::new(); - - // Construct the HIR map. - let hir_map = time(sess, "indexing HIR", || { - hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs) - }); - - let query_result_on_disk_cache = time(sess, "load query result cache", || { - rustc_incremental::load_query_result_cache(sess) - }); - let mut local_providers = ty::query::Providers::default(); - default_provide(&mut local_providers); - codegen_backend.provide(&mut local_providers); + // Construct the HIR map. + let hir_map = time(sess, "indexing HIR", || { + hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) + }); - let mut extern_providers = local_providers; - default_provide_extern(&mut extern_providers); - codegen_backend.provide_extern(&mut extern_providers); + let query_result_on_disk_cache = time(sess, "load query result cache", || { + rustc_incremental::load_query_result_cache(sess) + }); - if let Some(callback) = override_queries { - callback(sess, &mut local_providers, &mut extern_providers); - } + let codegen_backend = compiler.codegen_backend(); + let mut local_providers = ty::query::Providers::default(); + default_provide(&mut local_providers); + codegen_backend.provide(&mut local_providers); - let gcx = TyCtxt::create_global_ctxt( - sess, - lint_store, - local_providers, - extern_providers, - &arenas, - resolver_outputs, - hir_map, - query_result_on_disk_cache, - &crate_name, - &outputs - ); + let mut extern_providers = local_providers; + default_provide_extern(&mut extern_providers); + codegen_backend.provide_extern(&mut extern_providers); - global_ctxt = Some(gcx); - let gcx = global_ctxt.as_ref().unwrap(); - - ty::tls::enter_global(gcx, |tcx| { - // Do some initialization of the DepGraph that can only be done with the - // tcx available. - time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); - }); + if let Some(callback) = compiler.override_queries { + callback(sess, &mut local_providers, &mut extern_providers); + } - yield BoxedGlobalCtxt::initial_yield(()); - box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx)); + let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt( + sess, + lint_store, + local_providers, + extern_providers, + &all_arenas, + arena, + resolver_outputs, + hir_map, + query_result_on_disk_cache, + &crate_name, + &outputs + )); - if sess.opts.debugging_opts.query_stats { - gcx.queries.print_stats(); - } + // Do some initialization of the DepGraph that can only be done with the tcx available. + ty::tls::enter_global(&gcx, |tcx| { + time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); }); - result + QueryContext(gcx) } /// Runs the resolution, type-checking, region checking and other diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 9094f36d44e5e..6103d42c5dbcb 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,17 +1,19 @@ use crate::interface::{Compiler, Result}; -use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt}; +use crate::passes::{self, BoxedResolver, QueryContext}; use rustc_incremental::DepGraphFuture; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Once, WorkerLocal}; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; +use rustc::arena::Arena; use rustc::hir; use rustc::lint; use rustc::session::Session; use rustc::lint::LintStore; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::steal::Steal; -use rustc::ty::ResolverOutputs; +use rustc::ty::{AllArenas, ResolverOutputs, GlobalCtxt}; use rustc::dep_graph::DepGraph; use std::cell::{Ref, RefMut, RefCell}; use std::rc::Rc; @@ -44,13 +46,6 @@ impl Query { .unwrap() } - /// Returns a stolen query result. Panics if there's already a result. - pub fn give(&self, value: T) { - let mut result = self.result.borrow_mut(); - assert!(result.is_none(), "a result already exists"); - *result = Some(Ok(value)); - } - /// Borrows the query result using the RefCell. Panics if the result is stolen. pub fn peek(&self) -> Ref<'_, T> { Ref::map(self.result.borrow(), |r| { @@ -74,24 +69,54 @@ impl Default for Query { } } -#[derive(Default)] -pub(crate) struct Queries { +pub struct Queries<'tcx> { + compiler: &'tcx Compiler, + gcx: Once>, + + all_arenas: AllArenas, + arena: WorkerLocal>, + dep_graph_future: Query>, parse: Query, crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, expansion: Query<(ast::Crate, Steal>>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(Steal, Steal)>, + lower_to_hir: Query<(&'tcx hir::map::Forest, Steal)>, prepare_outputs: Query, - global_ctxt: Query, + global_ctxt: Query>, ongoing_codegen: Query>, - link: Query<()>, } -impl Compiler { +impl<'tcx> Queries<'tcx> { + pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> { + Queries { + compiler, + gcx: Once::new(), + all_arenas: AllArenas::new(), + arena: WorkerLocal::new(|_| Arena::default()), + dep_graph_future: Default::default(), + parse: Default::default(), + crate_name: Default::default(), + register_plugins: Default::default(), + expansion: Default::default(), + dep_graph: Default::default(), + lower_to_hir: Default::default(), + prepare_outputs: Default::default(), + global_ctxt: Default::default(), + ongoing_codegen: Default::default(), + } + } + + fn session(&self) -> &Lrc { + &self.compiler.sess + } + fn codegen_backend(&self) -> &Lrc> { + &self.compiler.codegen_backend() + } + pub fn dep_graph_future(&self) -> Result<&Query>> { - self.queries.dep_graph_future.compute(|| { + self.dep_graph_future.compute(|| { Ok(if self.session().opts.build_dep_graph() { Some(rustc_incremental::load_dep_graph(self.session())) } else { @@ -101,8 +126,8 @@ impl Compiler { } pub fn parse(&self) -> Result<&Query> { - self.queries.parse.compute(|| { - passes::parse(self.session(), &self.input).map_err( + self.parse.compute(|| { + passes::parse(self.session(), &self.compiler.input).map_err( |mut parse_error| { parse_error.emit(); ErrorReported @@ -112,7 +137,7 @@ impl Compiler { } pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc)>> { - self.queries.register_plugins.compute(|| { + self.register_plugins.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); @@ -120,7 +145,7 @@ impl Compiler { let result = passes::register_plugins( self.session(), &*self.codegen_backend().metadata_loader(), - self.register_lints + self.compiler.register_lints .as_ref() .map(|p| &**p) .unwrap_or_else(|| empty), @@ -140,8 +165,8 @@ impl Compiler { } pub fn crate_name(&self) -> Result<&Query> { - self.queries.crate_name.compute(|| { - Ok(match self.crate_name { + self.crate_name.compute(|| { + Ok(match self.compiler.crate_name { Some(ref crate_name) => crate_name.clone(), None => { let parse_result = self.parse()?; @@ -149,7 +174,7 @@ impl Compiler { rustc_codegen_utils::link::find_crate_name( Some(self.session()), &krate.attrs, - &self.input + &self.compiler.input ) } }) @@ -159,11 +184,11 @@ impl Compiler { pub fn expansion( &self ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { - self.queries.expansion.compute(|| { + self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let (krate, lint_store) = self.register_plugins()?.take(); passes::configure_and_expand( - self.sess.clone(), + self.session().clone(), lint_store.clone(), self.codegen_backend().metadata_loader(), krate, @@ -175,7 +200,7 @@ impl Compiler { } pub fn dep_graph(&self) -> Result<&Query> { - self.queries.dep_graph.compute(|| { + self.dep_graph.compute(|| { Ok(match self.dep_graph_future()?.take() { None => DepGraph::new_disabled(), Some(future) => { @@ -192,15 +217,15 @@ impl Compiler { } pub fn lower_to_hir( - &self, - ) -> Result<&Query<(Steal, Steal)>> { - self.queries.lower_to_hir.compute(|| { + &'tcx self, + ) -> Result<&Query<(&'tcx hir::map::Forest, Steal)>> { + self.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); let krate = &peeked.0; let resolver = peeked.1.steal(); let lint_store = &peeked.2; - let hir = Steal::new(resolver.borrow_mut().access(|resolver| { + let hir = resolver.borrow_mut().access(|resolver| { passes::lower_to_hir( self.session(), lint_store, @@ -208,41 +233,47 @@ impl Compiler { &*self.dep_graph()?.peek(), &krate ) - })?); + })?; + let hir = self.arena.alloc(hir); Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } pub fn prepare_outputs(&self) -> Result<&Query> { - self.queries.prepare_outputs.compute(|| { + self.prepare_outputs.compute(|| { let expansion_result = self.expansion()?; let (krate, boxed_resolver, _) = &*expansion_result.peek(); let crate_name = self.crate_name()?; let crate_name = crate_name.peek(); - passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name) + passes::prepare_outputs( + self.session(), self.compiler, &krate, &boxed_resolver, &crate_name + ) }) } - pub fn global_ctxt(&self) -> Result<&Query> { - self.queries.global_ctxt.compute(|| { + pub fn global_ctxt(&'tcx self) -> Result<&Query>> { + self.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); let lint_store = self.expansion()?.peek().2.clone(); - let hir = self.lower_to_hir()?; - let hir = hir.peek(); - let (hir_forest, resolver_outputs) = &*hir; + let hir = self.lower_to_hir()?.peek(); + let (ref hir_forest, ref resolver_outputs) = &*hir; Ok(passes::create_global_ctxt( - self, + self.compiler, lint_store, - hir_forest.steal(), + hir_forest, resolver_outputs.steal(), outputs, - &crate_name)) + &crate_name, + &self.gcx, + &self.all_arenas, + &self.arena, + )) }) } - pub fn ongoing_codegen(&self) -> Result<&Query>> { - self.queries.ongoing_codegen.compute(|| { + pub fn ongoing_codegen(&'tcx self) -> Result<&Query>> { + self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); @@ -259,22 +290,58 @@ impl Compiler { }) } - pub fn link(&self) -> Result<&Query<()>> { - self.queries.link.compute(|| { - let sess = self.session(); - - let ongoing_codegen = self.ongoing_codegen()?.take(); + pub fn linker(&'tcx self) -> Result { + let dep_graph = self.dep_graph()?; + let prepare_outputs = self.prepare_outputs()?; + let ongoing_codegen = self.ongoing_codegen()?; - self.codegen_backend().join_codegen_and_link( - ongoing_codegen, - sess, - &*self.dep_graph()?.peek(), - &*self.prepare_outputs()?.peek(), - ).map_err(|_| ErrorReported)?; + let sess = self.session().clone(); + let codegen_backend = self.codegen_backend().clone(); - Ok(()) + Ok(Linker { + sess, + dep_graph: dep_graph.peek().clone(), + prepare_outputs: prepare_outputs.take(), + ongoing_codegen: ongoing_codegen.take(), + codegen_backend, }) } +} + +pub struct Linker { + sess: Lrc, + dep_graph: DepGraph, + prepare_outputs: OutputFilenames, + ongoing_codegen: Box, + codegen_backend: Lrc>, +} + +impl Linker { + pub fn link(self) -> Result<()> { + self.codegen_backend.join_codegen_and_link( + self.ongoing_codegen, + &self.sess, + &self.dep_graph, + &self.prepare_outputs, + ).map_err(|_| ErrorReported) + } +} + +impl Compiler { + pub fn enter(&self, f: F) -> T + where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T + { + let queries = Queries::new(&self); + let ret = f(&queries); + + if self.session().opts.debugging_opts.query_stats { + if let Ok(gcx) = queries.global_ctxt() { + gcx.peek().print_stats(); + } + } + + ret + } // This method is different to all the other methods in `Compiler` because // it lacks a `Queries` entry. It's also not currently used. It does serve @@ -282,24 +349,30 @@ impl Compiler { // between some passes. And see `rustc_driver::run_compiler` for a more // complex example. pub fn compile(&self) -> Result<()> { - self.prepare_outputs()?; + let linker = self.enter(|queries| { + queries.prepare_outputs()?; - if self.session().opts.output_types.contains_key(&OutputType::DepInfo) - && self.session().opts.output_types.len() == 1 - { - return Ok(()) - } + if self.session().opts.output_types.contains_key(&OutputType::DepInfo) + && self.session().opts.output_types.len() == 1 + { + return Ok(None) + } + + queries.global_ctxt()?; - self.global_ctxt()?; + // Drop AST after creating GlobalCtxt to free memory. + mem::drop(queries.expansion()?.take()); - // Drop AST after creating GlobalCtxt to free memory. - mem::drop(self.expansion()?.take()); + queries.ongoing_codegen()?; - self.ongoing_codegen()?; + let linker = queries.linker()?; + Ok(Some(linker)) + })?; - // Drop GlobalCtxt after starting codegen to free memory. - mem::drop(self.global_ctxt()?.take()); + if let Some(linker) = linker { + linker.link()? + } - self.link().map(|_| ()) + Ok(()) } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 612f3c69871d7..7d1f89079f808 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -343,14 +343,14 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt registry: rustc_driver::diagnostics_registry(), }; - interface::run_compiler_in_existing_thread_pool(config, |compiler| { + interface::run_compiler_in_existing_thread_pool(config, |compiler| compiler.enter(|queries| { let sess = compiler.session(); // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. let resolver = { - let parts = abort_on_err(compiler.expansion(), sess).peek(); + let parts = abort_on_err(queries.expansion(), sess).peek(); let resolver = parts.1.borrow(); // Before we actually clone it, let's force all the extern'd crates to @@ -358,10 +358,11 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // intra-doc-links resolver.borrow_mut().access(|resolver| { for extern_name in &extern_names { - resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID) - .unwrap_or_else( - |()| panic!("Unable to resolve external crate {}", extern_name) - ); + resolver.resolve_str_path_error( + DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID + ).unwrap_or_else( + |()| panic!("Unable to resolve external crate {}", extern_name) + ); } }); @@ -373,7 +374,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt sess.fatal("Compilation failed, aborting rustdoc"); } - let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take(); + let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); global_ctxt.enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); @@ -447,8 +448,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }, sym::plugins => { report_deprecated_attr("plugins = \"...\"", diag); - eprintln!("WARNING: `#![doc(plugins = \"...\")]` no longer functions; \ - see CVE-2018-1000622"); + eprintln!("WARNING: `#![doc(plugins = \"...\")]` \ + no longer functions; see CVE-2018-1000622"); continue }, _ => continue, @@ -486,7 +487,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt (krate, ctxt.renderinfo.into_inner(), render_options) }) - }) + })) } /// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 22f209b8bada1..d09eb0b2fc263 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -85,14 +85,14 @@ pub fn run(options: Options) -> i32 { let mut test_args = options.test_args.clone(); let display_warnings = options.display_warnings; - let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> { - let lower_to_hir = compiler.lower_to_hir()?; + let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| { + let lower_to_hir = queries.lower_to_hir()?; - let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); + let mut opts = scrape_test_config(lower_to_hir.peek().0.krate()); opts.display_warnings |= options.display_warnings; let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( - compiler.crate_name()?.peek().to_string(), + queries.crate_name()?.peek().to_string(), options, false, opts, @@ -101,7 +101,8 @@ pub fn run(options: Options) -> i32 { enable_per_target_ignores, ); - let mut global_ctxt = compiler.global_ctxt()?.take(); + let mut global_ctxt = queries.global_ctxt()?.take(); + global_ctxt.enter(|tcx| { let krate = tcx.hir().krate(); let mut hir_collector = HirCollector { @@ -116,8 +117,9 @@ pub fn run(options: Options) -> i32 { }); }); - Ok(collector.tests) - }).expect("compiler aborted in rustdoc!"); + let ret : Result<_, ErrorReported> = Ok(collector.tests); + ret + })).expect("compiler aborted in rustdoc!"); test_args.insert(0, "rustdoctest".to_string()); diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index f9ecff2abaa83..62a66aefd2deb 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -66,6 +66,11 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { interface::run_compiler(config, |compiler| { // This runs all the passes prior to linking, too. - compiler.link().ok(); + let linker = compiler.enter(|queries| { + queries.linker() + }); + if let Ok(linker) = linker { + linker.link(); + } }); }