From 266ede1bb34195663238d23373bcc56f1f731748 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Nov 2019 15:59:22 +0100 Subject: [PATCH 01/11] Isolate compiler queries inside the Queries type. --- src/librustc_driver/lib.rs | 186 ++++++++++++++-------------- src/librustc_interface/interface.rs | 3 - src/librustc_interface/queries.rs | 117 +++++++++++------ src/librustdoc/core.rs | 54 ++++---- src/librustdoc/test.rs | 35 +++--- 5 files changed, 219 insertions(+), 176 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 13829b842fd5f..f28119fb66a3f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -283,120 +283,124 @@ 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, + compiler.enter(|queries| { + 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 sess.compile_status(); } - return sess.compile_status(); - } - if callbacks.after_parsing(compiler) == Compilation::Stop { - return sess.compile_status(); - } + if callbacks.after_parsing(compiler) == Compilation::Stop { + 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 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 sess.compile_status(); + } + + { + let (_, lint_store) = &*queries.register_plugins()?.peek(); - { - let (_, lint_store) = &*compiler.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); + queries.expansion()?; + if callbacks.after_expansion(compiler) == Compilation::Stop { return sess.compile_status(); } - } - compiler.expansion()?; - if callbacks.after_expansion(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.prepare_outputs()?; + + if sess.opts.output_types.contains_key(&OutputType::DepInfo) + && sess.opts.output_types.len() == 1 + { + return sess.compile_status(); + } - compiler.prepare_outputs()?; + queries.global_ctxt()?; - if sess.opts.output_types.contains_key(&OutputType::DepInfo) - && sess.opts.output_types.len() == 1 - { - return sess.compile_status(); - } + if sess.opts.debugging_opts.no_analysis || + sess.opts.debugging_opts.ast_json { + return sess.compile_status(); + } - compiler.global_ctxt()?; + 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) + ) + }); - if sess.opts.debugging_opts.no_analysis || - sess.opts.debugging_opts.ast_json { - return sess.compile_status(); - } + 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 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()); - } + queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; - compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; + if callbacks.after_analysis(compiler) == Compilation::Stop { + return sess.compile_status(); + } - if callbacks.after_analysis(compiler) == Compilation::Stop { - return sess.compile_status(); - } + if sess.opts.debugging_opts.save_analysis { + mem::drop(queries.expansion()?.take()); + } - if sess.opts.debugging_opts.save_analysis { - mem::drop(compiler.expansion()?.take()); - } + queries.ongoing_codegen()?; - compiler.ongoing_codegen()?; + // Drop GlobalCtxt after starting codegen to free memory + mem::drop(queries.global_ctxt()?.take()); - // Drop GlobalCtxt after starting codegen to free memory - mem::drop(compiler.global_ctxt()?.take()); + 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(); - } + queries.link()?; - compiler.link()?; + Ok(()) + })?; 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/queries.rs b/src/librustc_interface/queries.rs index 9094f36d44e5e..85bdd341f5272 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -3,6 +3,7 @@ use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt}; use rustc_incremental::DepGraphFuture; use rustc_data_structures::sync::Lrc; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; use rustc::hir; @@ -44,13 +45,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,8 +68,9 @@ impl Default for Query { } } -#[derive(Default)] -pub(crate) struct Queries { +pub struct Queries<'comp> { + compiler: &'comp Compiler, + dep_graph_future: Query>, parse: Query, crate_name: Query, @@ -89,9 +84,33 @@ pub(crate) struct Queries { link: Query<()>, } -impl Compiler { +impl<'comp> Queries<'comp> { + pub fn new(compiler: &'comp Compiler) -> Queries<'comp> { + Queries { + compiler, + 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(), + link: 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 +120,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 +131,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 +139,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 +159,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 +168,7 @@ impl Compiler { rustc_codegen_utils::link::find_crate_name( Some(self.session()), &krate.attrs, - &self.input + &self.compiler.input ) } }) @@ -159,11 +178,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 +194,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) => { @@ -194,7 +213,7 @@ impl Compiler { pub fn lower_to_hir( &self, ) -> Result<&Query<(Steal, Steal)>> { - self.queries.lower_to_hir.compute(|| { + self.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); let krate = &peeked.0; @@ -214,17 +233,17 @@ impl Compiler { } 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(|| { + 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(); @@ -232,7 +251,7 @@ impl Compiler { let hir = hir.peek(); let (hir_forest, resolver_outputs) = &*hir; Ok(passes::create_global_ctxt( - self, + self.compiler, lint_store, hir_forest.steal(), resolver_outputs.steal(), @@ -242,7 +261,7 @@ impl Compiler { } pub fn ongoing_codegen(&self) -> Result<&Query>> { - self.queries.ongoing_codegen.compute(|| { + self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); @@ -260,7 +279,7 @@ impl Compiler { } pub fn link(&self) -> Result<&Query<()>> { - self.queries.link.compute(|| { + self.link.compute(|| { let sess = self.session(); let ongoing_codegen = self.ongoing_codegen()?.take(); @@ -275,6 +294,20 @@ impl Compiler { Ok(()) }) } +} + +impl Compiler { + // 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 + // as an example of how `Compiler` can be used, with additional steps added + // between some passes. And see `rustc_driver::run_compiler` for a more + // complex example. + pub fn enter<'c, F, T>(&'c self, f: F) -> Result + where F: for<'q> FnOnce(&'q Queries<'c>) -> Result + { + let queries = Queries::new(&self); + f(&queries) + } // 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 +315,26 @@ impl Compiler { // between some passes. And see `rustc_driver::run_compiler` for a more // complex example. pub fn compile(&self) -> Result<()> { - self.prepare_outputs()?; + 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(()) + } - self.global_ctxt()?; + queries.global_ctxt()?; - // Drop AST after creating GlobalCtxt to free memory. - mem::drop(self.expansion()?.take()); + // Drop AST after creating GlobalCtxt to free memory. + mem::drop(queries.expansion()?.take()); - self.ongoing_codegen()?; + queries.ongoing_codegen()?; - // Drop GlobalCtxt after starting codegen to free memory. - mem::drop(self.global_ctxt()?.take()); + // Drop GlobalCtxt after starting codegen to free memory. + mem::drop(queries.global_ctxt()?.take()); - self.link().map(|_| ()) + queries.link().map(|_| ()) + }) } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 612f3c69871d7..15904814ac46d 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -346,34 +346,38 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt interface::run_compiler_in_existing_thread_pool(config, |compiler| { 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 resolver = parts.1.borrow(); - - // Before we actually clone it, let's force all the extern'd crates to - // actually be loaded, just in case they're only referred to inside - // 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) - ); - } - }); + let (resolver, mut global_ctxt) = compiler.enter(|queries| { + // 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(queries.expansion(), sess).peek(); + let resolver = parts.1.borrow(); + + // Before we actually clone it, let's force all the extern'd crates to + // actually be loaded, just in case they're only referred to inside + // 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) + ); + } + }); - // Now we're good to clone the resolver because everything should be loaded - resolver.clone() - }; + // Now we're good to clone the resolver because everything should be loaded + resolver.clone() + }; - if sess.has_errors() { - sess.fatal("Compilation failed, aborting rustdoc"); - } + if sess.has_errors() { + sess.fatal("Compilation failed, aborting rustdoc"); + } + + let global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take(); + Ok((resolver, global_ctxt)) + }).unwrap(); global_ctxt.enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 22f209b8bada1..eca542ea6a37c 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -86,22 +86,25 @@ pub fn run(options: Options) -> i32 { let display_warnings = options.display_warnings; let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> { - let lower_to_hir = compiler.lower_to_hir()?; - - let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().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(), - options, - false, - opts, - Some(compiler.source_map().clone()), - None, - enable_per_target_ignores, - ); - - let mut global_ctxt = compiler.global_ctxt()?.take(); + let (mut collector, mut global_ctxt) = compiler.enter(|queries| { + let lower_to_hir = queries.lower_to_hir()?; + + let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); + opts.display_warnings |= options.display_warnings; + let enable_per_target_ignores = options.enable_per_target_ignores; + let collector = Collector::new( + queries.crate_name()?.peek().to_string(), + options, + false, + opts, + Some(compiler.source_map().clone()), + None, + enable_per_target_ignores, + ); + + let global_ctxt = queries.global_ctxt()?.take(); + Ok((collector, global_ctxt)) + })?; global_ctxt.enter(|tcx| { let krate = tcx.hir().krate(); let mut hir_collector = HirCollector { From 5098ba6a932785152285d5729708f7d58f795b62 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Nov 2019 16:32:57 +0100 Subject: [PATCH 02/11] Move linking ouside the interface queries. --- src/librustc_driver/lib.rs | 35 +++++++++++------ src/librustc_interface/queries.rs | 64 +++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 32 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f28119fb66a3f..b4dab3979961b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -283,7 +283,7 @@ pub fn run_compiler( return sess.compile_status(); } - compiler.enter(|queries| { + let linker = compiler.enter(|queries| { queries.parse()?; if let Some(ppm) = &sess.opts.pretty { @@ -309,17 +309,20 @@ pub fn run_compiler( compiler.output_file().as_ref().map(|p| &**p), ); } - return sess.compile_status(); + sess.compile_status()?; + return Ok(None); } if callbacks.after_parsing(compiler) == Compilation::Stop { - return sess.compile_status(); + sess.compile_status()?; + return Ok(None); } 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(); + sess.compile_status()?; + return Ok(None); } { @@ -328,13 +331,15 @@ pub fn run_compiler( // 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(); + sess.compile_status()?; + return Ok(None); } } queries.expansion()?; if callbacks.after_expansion(compiler) == Compilation::Stop { - return sess.compile_status(); + sess.compile_status()?; + return Ok(None); } queries.prepare_outputs()?; @@ -342,14 +347,16 @@ pub fn run_compiler( if sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1 { - return sess.compile_status(); + sess.compile_status()?; + return Ok(None); } queries.global_ctxt()?; if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json { - return sess.compile_status(); + sess.compile_status()?; + return Ok(None); } if sess.opts.debugging_opts.save_analysis { @@ -381,7 +388,8 @@ pub fn run_compiler( queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; if callbacks.after_analysis(compiler) == Compilation::Stop { - return sess.compile_status(); + sess.compile_status()?; + return Ok(None); } if sess.opts.debugging_opts.save_analysis { @@ -397,11 +405,14 @@ pub fn run_compiler( sess.code_stats.print_type_sizes(); } - queries.link()?; - - Ok(()) + 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/queries.rs b/src/librustc_interface/queries.rs index 85bdd341f5272..e91316ff4772c 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -81,7 +81,6 @@ pub struct Queries<'comp> { prepare_outputs: Query, global_ctxt: Query, ongoing_codegen: Query>, - link: Query<()>, } impl<'comp> Queries<'comp> { @@ -98,7 +97,6 @@ impl<'comp> Queries<'comp> { prepare_outputs: Default::default(), global_ctxt: Default::default(), ongoing_codegen: Default::default(), - link: Default::default(), } } @@ -278,24 +276,43 @@ impl<'comp> Queries<'comp> { }) } - pub fn link(&self) -> Result<&Query<()>> { - self.link.compute(|| { - let sess = self.session(); + pub fn linker(self) -> Result { + let dep_graph = self.dep_graph()?; + let prepare_outputs = self.prepare_outputs()?; + let ongoing_codegen = self.ongoing_codegen()?; - let ongoing_codegen = self.ongoing_codegen()?.take(); + let sess = self.session().clone(); + let codegen_backend = self.codegen_backend().clone(); - self.codegen_backend().join_codegen_and_link( - ongoing_codegen, - sess, - &*self.dep_graph()?.peek(), - &*self.prepare_outputs()?.peek(), - ).map_err(|_| ErrorReported)?; - - Ok(()) + Ok(Linker { + sess, + dep_graph: dep_graph.take(), + 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 { // 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 @@ -303,10 +320,10 @@ impl Compiler { // between some passes. And see `rustc_driver::run_compiler` for a more // complex example. pub fn enter<'c, F, T>(&'c self, f: F) -> Result - where F: for<'q> FnOnce(&'q Queries<'c>) -> Result + where F: FnOnce(Queries<'c>) -> Result { let queries = Queries::new(&self); - f(&queries) + f(queries) } // This method is different to all the other methods in `Compiler` because @@ -315,13 +332,13 @@ impl Compiler { // between some passes. And see `rustc_driver::run_compiler` for a more // complex example. pub fn compile(&self) -> Result<()> { - self.enter(|queries| { + 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(()) + return Ok(None) } queries.global_ctxt()?; @@ -334,7 +351,14 @@ impl Compiler { // Drop GlobalCtxt after starting codegen to free memory. mem::drop(queries.global_ctxt()?.take()); - queries.link().map(|_| ()) - }) + let linker = queries.linker()?; + Ok(Some(linker)) + })?; + + if let Some(linker) = linker { + linker.link()? + } + + Ok(()) } } From 27513a21c4bea1774c295c398af413631807cb5c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Nov 2019 16:41:43 +0100 Subject: [PATCH 03/11] Tidy. --- src/librustc_driver/lib.rs | 4 +++- src/librustc_interface/queries.rs | 4 +++- src/librustdoc/core.rs | 9 +++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b4dab3979961b..2429cbe3f5e63 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -372,7 +372,9 @@ pub fn run_compiler( &crate_name, &compiler.input(), None, - DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name) + DumpHandler::new( + compiler.output_dir().as_ref().map(|p| &**p), &crate_name + ) ) }); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index e91316ff4772c..013c986288a6e 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -236,7 +236,9 @@ impl<'comp> Queries<'comp> { 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.compiler, &krate, &boxed_resolver, &crate_name) + passes::prepare_outputs( + self.session(), self.compiler, &krate, &boxed_resolver, &crate_name + ) }) } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 15904814ac46d..02045b0dec8a6 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -359,10 +359,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) + ); } }); From becfe5c15334ecc80e22e024d0137fb9dc0f4d08 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Nov 2019 21:12:38 +0100 Subject: [PATCH 04/11] Fix test. --- src/test/run-make-fulldeps/issue-19371/foo.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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(); + } }); } From 18bb9129840bc62f083f93d6518a50b4df5bb3b1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Nov 2019 17:24:11 +0100 Subject: [PATCH 05/11] Remove wrong comment. --- src/librustc_interface/queries.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 013c986288a6e..1a510763d6bac 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -316,11 +316,6 @@ impl Linker { } impl Compiler { - // 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 - // as an example of how `Compiler` can be used, with additional steps added - // between some passes. And see `rustc_driver::run_compiler` for a more - // complex example. pub fn enter<'c, F, T>(&'c self, f: F) -> Result where F: FnOnce(Queries<'c>) -> Result { From ea1b8039ada203a50342fda342f905c932cd4eef Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Nov 2019 17:25:47 +0100 Subject: [PATCH 06/11] Pass Queries by reference. --- src/librustc_interface/queries.rs | 10 +++++----- src/librustdoc/core.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 1a510763d6bac..574a24551242b 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -278,7 +278,7 @@ impl<'comp> Queries<'comp> { }) } - pub fn linker(self) -> Result { + pub fn linker(&self) -> Result { let dep_graph = self.dep_graph()?; let prepare_outputs = self.prepare_outputs()?; let ongoing_codegen = self.ongoing_codegen()?; @@ -288,7 +288,7 @@ impl<'comp> Queries<'comp> { Ok(Linker { sess, - dep_graph: dep_graph.take(), + dep_graph: dep_graph.peek().clone(), prepare_outputs: prepare_outputs.take(), ongoing_codegen: ongoing_codegen.take(), codegen_backend, @@ -316,11 +316,11 @@ impl Linker { } impl Compiler { - pub fn enter<'c, F, T>(&'c self, f: F) -> Result - where F: FnOnce(Queries<'c>) -> Result + pub fn enter<'c, F, T>(&'c self, f: F) -> T + where F: for<'q> FnOnce(&'q Queries<'c>) -> T { let queries = Queries::new(&self); - f(queries) + f(&queries) } // This method is different to all the other methods in `Compiler` because diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 02045b0dec8a6..ebd100e62d46e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -377,8 +377,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - Ok((resolver, global_ctxt)) - }).unwrap(); + (resolver, global_ctxt) + }); global_ctxt.enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); From 7d01b6ccf0232c8bb1de73033d05c3e5e89b463f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Nov 2019 17:29:32 +0100 Subject: [PATCH 07/11] Simplify early exits. --- src/librustc_driver/lib.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2429cbe3f5e63..7cafc05e39089 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -284,6 +284,7 @@ pub fn run_compiler( } let linker = compiler.enter(|queries| { + let early_exit = || sess.compile_status().map(|_| None); queries.parse()?; if let Some(ppm) = &sess.opts.pretty { @@ -309,20 +310,17 @@ pub fn run_compiler( compiler.output_file().as_ref().map(|p| &**p), ); } - sess.compile_status()?; - return Ok(None); + return early_exit(); } if callbacks.after_parsing(compiler) == Compilation::Stop { - sess.compile_status()?; - return Ok(None); + 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 { - sess.compile_status()?; - return Ok(None); + return early_exit(); } { @@ -331,15 +329,13 @@ pub fn run_compiler( // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { describe_lints(&sess, &lint_store, true); - sess.compile_status()?; - return Ok(None); + return early_exit(); } } queries.expansion()?; if callbacks.after_expansion(compiler) == Compilation::Stop { - sess.compile_status()?; - return Ok(None); + return early_exit(); } queries.prepare_outputs()?; @@ -347,16 +343,14 @@ pub fn run_compiler( if sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1 { - sess.compile_status()?; - return Ok(None); + return early_exit(); } queries.global_ctxt()?; if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json { - sess.compile_status()?; - return Ok(None); + return early_exit(); } if sess.opts.debugging_opts.save_analysis { @@ -390,8 +384,7 @@ pub fn run_compiler( queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; if callbacks.after_analysis(compiler) == Compilation::Stop { - sess.compile_status()?; - return Ok(None); + return early_exit(); } if sess.opts.debugging_opts.save_analysis { From 8ffc9444a3275079ce24883ec57b041485c358a3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Nov 2019 18:19:08 +0100 Subject: [PATCH 08/11] Don't move stuff out of Compiler::enter. --- src/librustdoc/core.rs | 206 ++++++++++++++++++++--------------------- src/librustdoc/test.rs | 36 +++---- 2 files changed, 120 insertions(+), 122 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ebd100e62d46e..b5b331928b967 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -344,9 +344,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }; interface::run_compiler_in_existing_thread_pool(config, |compiler| { - let sess = compiler.session(); + compiler.enter(|queries| { + let sess = compiler.session(); - let (resolver, mut global_ctxt) = compiler.enter(|queries| { // 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. @@ -375,121 +375,119 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt sess.fatal("Compilation failed, aborting rustdoc"); } - let global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - - (resolver, global_ctxt) - }); - - global_ctxt.enter(|tcx| { - tcx.analysis(LOCAL_CRATE).ok(); - - // Abort if there were any errors so far - sess.abort_if_errors(); - - let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); - // Convert from a HirId set to a DefId set since we don't always have easy access - // to the map from defid -> hirid - let access_levels = AccessLevels { - map: access_levels.map.iter() - .map(|(&k, &v)| (tcx.hir().local_def_id(k), v)) - .collect() - }; - - let mut renderinfo = RenderInfo::default(); - renderinfo.access_levels = access_levels; - - let mut ctxt = DocContext { - tcx, - resolver, - external_traits: Default::default(), - active_extern_traits: Default::default(), - renderinfo: RefCell::new(renderinfo), - ty_substs: Default::default(), - lt_substs: Default::default(), - ct_substs: Default::default(), - impl_trait_bounds: Default::default(), - fake_def_ids: Default::default(), - all_fake_def_ids: Default::default(), - generated_synthetics: Default::default(), - auto_traits: tcx.all_traits(LOCAL_CRATE).iter().cloned().filter(|trait_def_id| { - tcx.trait_is_auto(*trait_def_id) - }).collect(), - }; - debug!("crate: {:?}", tcx.hir().krate()); - - let mut krate = clean::krate(&mut ctxt); - - fn report_deprecated_attr(name: &str, diag: &errors::Handler) { - let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ - considered deprecated", name)); - msg.warn("please see https://github.com/rust-lang/rust/issues/44136"); + let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); + + global_ctxt.enter(|tcx| { + tcx.analysis(LOCAL_CRATE).ok(); + + // Abort if there were any errors so far + sess.abort_if_errors(); + + let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); + // Convert from a HirId set to a DefId set since we don't always have easy access + // to the map from defid -> hirid + let access_levels = AccessLevels { + map: access_levels.map.iter() + .map(|(&k, &v)| (tcx.hir().local_def_id(k), v)) + .collect() + }; + + let mut renderinfo = RenderInfo::default(); + renderinfo.access_levels = access_levels; + + let mut ctxt = DocContext { + tcx, + resolver, + external_traits: Default::default(), + active_extern_traits: Default::default(), + renderinfo: RefCell::new(renderinfo), + ty_substs: Default::default(), + lt_substs: Default::default(), + ct_substs: Default::default(), + impl_trait_bounds: Default::default(), + fake_def_ids: Default::default(), + all_fake_def_ids: Default::default(), + generated_synthetics: Default::default(), + auto_traits: tcx.all_traits(LOCAL_CRATE).iter().cloned().filter(|trait_def_id| { + tcx.trait_is_auto(*trait_def_id) + }).collect(), + }; + debug!("crate: {:?}", tcx.hir().krate()); + + let mut krate = clean::krate(&mut ctxt); + + fn report_deprecated_attr(name: &str, diag: &errors::Handler) { + let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ + considered deprecated", name)); + msg.warn("please see https://github.com/rust-lang/rust/issues/44136"); + + if name == "no_default_passes" { + msg.help("you may want to use `#![doc(document_private_items)]`"); + } - if name == "no_default_passes" { - msg.help("you may want to use `#![doc(document_private_items)]`"); + msg.emit(); } - msg.emit(); - } - - // Process all of the crate attributes, extracting plugin metadata along - // with the passes which we are supposed to run. - for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { - let diag = ctxt.sess().diagnostic(); - - let name = attr.name_or_empty(); - if attr.is_word() { - if name == sym::no_default_passes { - report_deprecated_attr("no_default_passes", diag); - if default_passes == passes::DefaultPassOption::Default { - default_passes = passes::DefaultPassOption::None; + // Process all of the crate attributes, extracting plugin metadata along + // with the passes which we are supposed to run. + for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { + let diag = ctxt.sess().diagnostic(); + + let name = attr.name_or_empty(); + if attr.is_word() { + if name == sym::no_default_passes { + report_deprecated_attr("no_default_passes", diag); + if default_passes == passes::DefaultPassOption::Default { + default_passes = passes::DefaultPassOption::None; + } + } + } else if let Some(value) = attr.value_str() { + let sink = match name { + sym::passes => { + report_deprecated_attr("passes = \"...\"", diag); + &mut manual_passes + }, + sym::plugins => { + report_deprecated_attr("plugins = \"...\"", diag); + eprintln!("WARNING: `#![doc(plugins = \"...\")]` \ + no longer functions; see CVE-2018-1000622"); + continue + }, + _ => continue, + }; + for name in value.as_str().split_whitespace() { + sink.push(name.to_string()); } } - } else if let Some(value) = attr.value_str() { - let sink = match name { - sym::passes => { - report_deprecated_attr("passes = \"...\"", diag); - &mut manual_passes - }, - sym::plugins => { - report_deprecated_attr("plugins = \"...\"", diag); - eprintln!("WARNING: `#![doc(plugins = \"...\")]` no longer functions; \ - see CVE-2018-1000622"); - continue - }, - _ => continue, - }; - for name in value.as_str().split_whitespace() { - sink.push(name.to_string()); - } - } - if attr.is_word() && name == sym::document_private_items { - if default_passes == passes::DefaultPassOption::Default { - default_passes = passes::DefaultPassOption::Private; + if attr.is_word() && name == sym::document_private_items { + if default_passes == passes::DefaultPassOption::Default { + default_passes = passes::DefaultPassOption::Private; + } } } - } - let passes = passes::defaults(default_passes).iter().chain(manual_passes.into_iter() - .flat_map(|name| { - if let Some(pass) = passes::find_pass(&name) { - Some(pass) - } else { - error!("unknown pass {}, skipping", name); - None - } - })); + let passes = passes::defaults(default_passes).iter().chain(manual_passes.into_iter() + .flat_map(|name| { + if let Some(pass) = passes::find_pass(&name) { + Some(pass) + } else { + error!("unknown pass {}, skipping", name); + None + } + })); - info!("Executing passes"); + info!("Executing passes"); - for pass in passes { - debug!("running pass {}", pass.name); - krate = (pass.pass)(krate, &ctxt); - } + for pass in passes { + debug!("running pass {}", pass.name); + krate = (pass.pass)(krate, &ctxt); + } - ctxt.sess().abort_if_errors(); + ctxt.sess().abort_if_errors(); - (krate, ctxt.renderinfo.into_inner(), render_options) + (krate, ctxt.renderinfo.into_inner(), render_options) + }) }) }) } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index eca542ea6a37c..47eb993dfc31b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -86,13 +86,13 @@ pub fn run(options: Options) -> i32 { let display_warnings = options.display_warnings; let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> { - let (mut collector, mut global_ctxt) = compiler.enter(|queries| { + compiler.enter(|queries| { let lower_to_hir = queries.lower_to_hir()?; let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); opts.display_warnings |= options.display_warnings; let enable_per_target_ignores = options.enable_per_target_ignores; - let collector = Collector::new( + let mut collector = Collector::new( queries.crate_name()?.peek().to_string(), options, false, @@ -102,24 +102,24 @@ pub fn run(options: Options) -> i32 { enable_per_target_ignores, ); - let global_ctxt = queries.global_ctxt()?.take(); - Ok((collector, global_ctxt)) - })?; - global_ctxt.enter(|tcx| { - let krate = tcx.hir().krate(); - let mut hir_collector = HirCollector { - sess: compiler.session(), - collector: &mut collector, - map: tcx.hir(), - codes: ErrorCodes::from(compiler.session().opts - .unstable_features.is_nightly_build()), - }; - hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { - intravisit::walk_crate(this, krate); + let mut global_ctxt = queries.global_ctxt()?.take(); + + global_ctxt.enter(|tcx| { + let krate = tcx.hir().krate(); + let mut hir_collector = HirCollector { + sess: compiler.session(), + collector: &mut collector, + map: tcx.hir(), + codes: ErrorCodes::from(compiler.session().opts + .unstable_features.is_nightly_build()), + }; + hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { + intravisit::walk_crate(this, krate); + }); }); - }); - Ok(collector.tests) + Ok(collector.tests) + }) }).expect("compiler aborted in rustdoc!"); test_args.insert(0, "rustdoctest".to_string()); From 9d5f721406d7ec1cb0197181a03bd266d66fd6c1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Nov 2019 18:36:18 +0100 Subject: [PATCH 09/11] Superfluous lifetime. --- src/librustc_interface/queries.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 574a24551242b..ba855ef2f8563 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -316,8 +316,8 @@ impl Linker { } impl Compiler { - pub fn enter<'c, F, T>(&'c self, f: F) -> T - where F: for<'q> FnOnce(&'q Queries<'c>) -> T + pub fn enter(&self, f: F) -> T + where F: for<'q> FnOnce(&'q Queries<'_>) -> T { let queries = Queries::new(&self); f(&queries) From 68b1ac98744b8e03bbcc5ab38f3afbd04f1ec097 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 12:16:36 +0100 Subject: [PATCH 10/11] Reduce righward drift. --- src/librustdoc/core.rs | 256 ++++++++++++++++++++--------------------- src/librustdoc/test.rs | 67 ++++++----- 2 files changed, 160 insertions(+), 163 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b5b331928b967..d9d475813b073 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -343,153 +343,151 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt registry: rustc_driver::diagnostics_registry(), }; - 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(queries.expansion(), sess).peek(); - let resolver = parts.1.borrow(); - - // Before we actually clone it, let's force all the extern'd crates to - // actually be loaded, just in case they're only referred to inside - // 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) - ); - } - }); + 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(queries.expansion(), sess).peek(); + let resolver = parts.1.borrow(); + + // Before we actually clone it, let's force all the extern'd crates to + // actually be loaded, just in case they're only referred to inside + // 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) + ); + } + }); + + // Now we're good to clone the resolver because everything should be loaded + resolver.clone() + }; + + if sess.has_errors() { + sess.fatal("Compilation failed, aborting rustdoc"); + } + + let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - // Now we're good to clone the resolver because everything should be loaded - resolver.clone() + global_ctxt.enter(|tcx| { + tcx.analysis(LOCAL_CRATE).ok(); + + // Abort if there were any errors so far + sess.abort_if_errors(); + + let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); + // Convert from a HirId set to a DefId set since we don't always have easy access + // to the map from defid -> hirid + let access_levels = AccessLevels { + map: access_levels.map.iter() + .map(|(&k, &v)| (tcx.hir().local_def_id(k), v)) + .collect() }; - if sess.has_errors() { - sess.fatal("Compilation failed, aborting rustdoc"); - } + let mut renderinfo = RenderInfo::default(); + renderinfo.access_levels = access_levels; + + let mut ctxt = DocContext { + tcx, + resolver, + external_traits: Default::default(), + active_extern_traits: Default::default(), + renderinfo: RefCell::new(renderinfo), + ty_substs: Default::default(), + lt_substs: Default::default(), + ct_substs: Default::default(), + impl_trait_bounds: Default::default(), + fake_def_ids: Default::default(), + all_fake_def_ids: Default::default(), + generated_synthetics: Default::default(), + auto_traits: tcx.all_traits(LOCAL_CRATE).iter().cloned().filter(|trait_def_id| { + tcx.trait_is_auto(*trait_def_id) + }).collect(), + }; + debug!("crate: {:?}", tcx.hir().krate()); - let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - - global_ctxt.enter(|tcx| { - tcx.analysis(LOCAL_CRATE).ok(); - - // Abort if there were any errors so far - sess.abort_if_errors(); - - let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); - // Convert from a HirId set to a DefId set since we don't always have easy access - // to the map from defid -> hirid - let access_levels = AccessLevels { - map: access_levels.map.iter() - .map(|(&k, &v)| (tcx.hir().local_def_id(k), v)) - .collect() - }; - - let mut renderinfo = RenderInfo::default(); - renderinfo.access_levels = access_levels; - - let mut ctxt = DocContext { - tcx, - resolver, - external_traits: Default::default(), - active_extern_traits: Default::default(), - renderinfo: RefCell::new(renderinfo), - ty_substs: Default::default(), - lt_substs: Default::default(), - ct_substs: Default::default(), - impl_trait_bounds: Default::default(), - fake_def_ids: Default::default(), - all_fake_def_ids: Default::default(), - generated_synthetics: Default::default(), - auto_traits: tcx.all_traits(LOCAL_CRATE).iter().cloned().filter(|trait_def_id| { - tcx.trait_is_auto(*trait_def_id) - }).collect(), - }; - debug!("crate: {:?}", tcx.hir().krate()); - - let mut krate = clean::krate(&mut ctxt); - - fn report_deprecated_attr(name: &str, diag: &errors::Handler) { - let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ - considered deprecated", name)); - msg.warn("please see https://github.com/rust-lang/rust/issues/44136"); - - if name == "no_default_passes" { - msg.help("you may want to use `#![doc(document_private_items)]`"); - } + let mut krate = clean::krate(&mut ctxt); + + fn report_deprecated_attr(name: &str, diag: &errors::Handler) { + let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ + considered deprecated", name)); + msg.warn("please see https://github.com/rust-lang/rust/issues/44136"); - msg.emit(); + if name == "no_default_passes" { + msg.help("you may want to use `#![doc(document_private_items)]`"); } - // Process all of the crate attributes, extracting plugin metadata along - // with the passes which we are supposed to run. - for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { - let diag = ctxt.sess().diagnostic(); - - let name = attr.name_or_empty(); - if attr.is_word() { - if name == sym::no_default_passes { - report_deprecated_attr("no_default_passes", diag); - if default_passes == passes::DefaultPassOption::Default { - default_passes = passes::DefaultPassOption::None; - } - } - } else if let Some(value) = attr.value_str() { - let sink = match name { - sym::passes => { - report_deprecated_attr("passes = \"...\"", diag); - &mut manual_passes - }, - sym::plugins => { - report_deprecated_attr("plugins = \"...\"", diag); - eprintln!("WARNING: `#![doc(plugins = \"...\")]` \ - no longer functions; see CVE-2018-1000622"); - continue - }, - _ => continue, - }; - for name in value.as_str().split_whitespace() { - sink.push(name.to_string()); - } - } + msg.emit(); + } + + // Process all of the crate attributes, extracting plugin metadata along + // with the passes which we are supposed to run. + for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { + let diag = ctxt.sess().diagnostic(); - if attr.is_word() && name == sym::document_private_items { + let name = attr.name_or_empty(); + if attr.is_word() { + if name == sym::no_default_passes { + report_deprecated_attr("no_default_passes", diag); if default_passes == passes::DefaultPassOption::Default { - default_passes = passes::DefaultPassOption::Private; + default_passes = passes::DefaultPassOption::None; } } + } else if let Some(value) = attr.value_str() { + let sink = match name { + sym::passes => { + report_deprecated_attr("passes = \"...\"", diag); + &mut manual_passes + }, + sym::plugins => { + report_deprecated_attr("plugins = \"...\"", diag); + eprintln!("WARNING: `#![doc(plugins = \"...\")]` \ + no longer functions; see CVE-2018-1000622"); + continue + }, + _ => continue, + }; + for name in value.as_str().split_whitespace() { + sink.push(name.to_string()); + } } - let passes = passes::defaults(default_passes).iter().chain(manual_passes.into_iter() - .flat_map(|name| { - if let Some(pass) = passes::find_pass(&name) { - Some(pass) - } else { - error!("unknown pass {}, skipping", name); - None - } - })); + if attr.is_word() && name == sym::document_private_items { + if default_passes == passes::DefaultPassOption::Default { + default_passes = passes::DefaultPassOption::Private; + } + } + } + + let passes = passes::defaults(default_passes).iter().chain(manual_passes.into_iter() + .flat_map(|name| { + if let Some(pass) = passes::find_pass(&name) { + Some(pass) + } else { + error!("unknown pass {}, skipping", name); + None + } + })); - info!("Executing passes"); + info!("Executing passes"); - for pass in passes { - debug!("running pass {}", pass.name); - krate = (pass.pass)(krate, &ctxt); - } + for pass in passes { + debug!("running pass {}", pass.name); + krate = (pass.pass)(krate, &ctxt); + } - ctxt.sess().abort_if_errors(); + ctxt.sess().abort_if_errors(); - (krate, ctxt.renderinfo.into_inner(), render_options) - }) + (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 47eb993dfc31b..4cb97ccb0bf63 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -85,42 +85,41 @@ 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> { - compiler.enter(|queries| { - let lower_to_hir = queries.lower_to_hir()?; - - let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); - opts.display_warnings |= options.display_warnings; - let enable_per_target_ignores = options.enable_per_target_ignores; - let mut collector = Collector::new( - queries.crate_name()?.peek().to_string(), - options, - false, - opts, - Some(compiler.source_map().clone()), - None, - enable_per_target_ignores, - ); - - let mut global_ctxt = queries.global_ctxt()?.take(); - - global_ctxt.enter(|tcx| { - let krate = tcx.hir().krate(); - let mut hir_collector = HirCollector { - sess: compiler.session(), - collector: &mut collector, - map: tcx.hir(), - codes: ErrorCodes::from(compiler.session().opts - .unstable_features.is_nightly_build()), - }; - hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { - intravisit::walk_crate(this, krate); - }); + 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()); + opts.display_warnings |= options.display_warnings; + let enable_per_target_ignores = options.enable_per_target_ignores; + let mut collector = Collector::new( + queries.crate_name()?.peek().to_string(), + options, + false, + opts, + Some(compiler.source_map().clone()), + None, + enable_per_target_ignores, + ); + + let mut global_ctxt = queries.global_ctxt()?.take(); + + global_ctxt.enter(|tcx| { + let krate = tcx.hir().krate(); + let mut hir_collector = HirCollector { + sess: compiler.session(), + collector: &mut collector, + map: tcx.hir(), + codes: ErrorCodes::from(compiler.session().opts + .unstable_features.is_nightly_build()), + }; + hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { + intravisit::walk_crate(this, krate); }); + }); - 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()); From 144d1c217151bbb6fea6a93a22e9dc9bfabae77f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 17:20:32 +0100 Subject: [PATCH 11/11] Review nits. --- src/librustc_driver/lib.rs | 3 --- src/librustc_interface/queries.rs | 5 +---- src/librustdoc/core.rs | 4 ++-- src/librustdoc/test.rs | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 7cafc05e39089..c945de8f1e1dc 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -393,9 +393,6 @@ pub fn run_compiler( queries.ongoing_codegen()?; - // Drop GlobalCtxt after starting codegen to free memory - mem::drop(queries.global_ctxt()?.take()); - if sess.opts.debugging_opts.print_type_sizes { sess.code_stats.print_type_sizes(); } diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index ba855ef2f8563..3b03cfc12bc11 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -317,7 +317,7 @@ impl Linker { impl Compiler { pub fn enter(&self, f: F) -> T - where F: for<'q> FnOnce(&'q Queries<'_>) -> T + where F: FnOnce(&Queries<'_>) -> T { let queries = Queries::new(&self); f(&queries) @@ -345,9 +345,6 @@ impl Compiler { queries.ongoing_codegen()?; - // Drop GlobalCtxt after starting codegen to free memory. - mem::drop(queries.global_ctxt()?.take()); - let linker = queries.linker()?; Ok(Some(linker)) })?; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index d9d475813b073..7d1f89079f808 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -343,7 +343,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt registry: rustc_driver::diagnostics_registry(), }; - interface::run_compiler_in_existing_thread_pool(config, |compiler| { compiler.enter(|queries| { + 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 @@ -487,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 4cb97ccb0bf63..44d3dac16606b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -85,7 +85,7 @@ 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| { compiler.enter(|queries| { + 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()); @@ -119,7 +119,7 @@ pub fn run(options: Options) -> i32 { let ret : Result<_, ErrorReported> = Ok(collector.tests); ret - }) }).expect("compiler aborted in rustdoc!"); + })).expect("compiler aborted in rustdoc!"); test_args.insert(0, "rustdoctest".to_string());