From 266ede1bb34195663238d23373bcc56f1f731748 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Nov 2019 15:59:22 +0100 Subject: [PATCH 01/43] 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/43] 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/43] 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/43] 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 cd5d0c7b102d2573165efdbd2ffc31c4a5be3bb5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 25 Nov 2019 12:14:23 +0100 Subject: [PATCH 05/43] Rename continue_panic_fmt to panic_handler, and make it the #[panic_handler] directly The "continue" in the name was really confusing; it sounds way too much like "resume" which is a totally different concept around panics. --- src/libstd/panicking.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 6819a4a04d737..a0f6183d514ea 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -296,14 +296,6 @@ pub fn panicking() -> bool { update_panic_count(0) != 0 } -/// Entry point of panic from the libcore crate (`panic_impl` lang item). -#[cfg(not(test))] -#[panic_handler] -#[unwind(allowed)] -pub fn rust_begin_panic(info: &PanicInfo<'_>) -> ! { - continue_panic_fmt(&info) -} - /// The entry point for panicking with a formatted message. /// /// This is designed to reduce the amount of code required at the call @@ -327,10 +319,13 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>, let (file, line, col) = *file_line_col; let location = Location::internal_constructor(file, line, col); let info = PanicInfo::internal_constructor(Some(msg), &location); - continue_panic_fmt(&info) + panic_handler(&info) } -fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! { +/// Entry point of panic from the libcore crate (`panic_impl` lang item). +#[cfg_attr(not(test), panic_handler)] +#[unwind(allowed)] +fn panic_handler(info: &PanicInfo<'_>) -> ! { struct PanicPayload<'a> { inner: &'a fmt::Arguments<'a>, string: Option, From 08f779cb4b481be58eeb5ecc421f69503780e8b1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 25 Nov 2019 12:16:08 +0100 Subject: [PATCH 06/43] better comment and rename BoxMeUp::box_me_up to take_box --- src/libcore/panic.rs | 4 +++- src/libpanic_unwind/lib.rs | 2 +- src/libstd/panicking.rs | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index cdd38449a1be2..0abc481f6e53b 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -266,6 +266,8 @@ impl fmt::Display for Location<'_> { #[unstable(feature = "std_internals", issue = "0")] #[doc(hidden)] pub unsafe trait BoxMeUp { - fn box_me_up(&mut self) -> *mut (dyn Any + Send); + /// The return type is actually `Box`, but we cannot use `Box` in libcore. + /// After this method got called, only some dummy default value is left in `self`. + fn take_box(&mut self) -> *mut (dyn Any + Send); fn get(&mut self) -> &(dyn Any + Send); } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index d97a7a8a87d8d..0c834e5c2a05c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -94,5 +94,5 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), #[unwind(allowed)] pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { let payload = payload as *mut &mut dyn BoxMeUp; - imp::panic(Box::from_raw((*payload).box_me_up())) + imp::panic(Box::from_raw((*payload).take_box())) } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index a0f6183d514ea..a16eec45b9aa1 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -340,6 +340,7 @@ fn panic_handler(info: &PanicInfo<'_>) -> ! { use crate::fmt::Write; let inner = self.inner; + // Lazily, the first time this gets called, run the actual string formatting. self.string.get_or_insert_with(|| { let mut s = String::new(); drop(s.write_fmt(*inner)); @@ -349,7 +350,7 @@ fn panic_handler(info: &PanicInfo<'_>) -> ! { } unsafe impl<'a> BoxMeUp for PanicPayload<'a> { - fn box_me_up(&mut self) -> *mut (dyn Any + Send) { + fn take_box(&mut self) -> *mut (dyn Any + Send) { let contents = mem::take(self.fill()); Box::into_raw(Box::new(contents)) } @@ -407,10 +408,10 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 } unsafe impl BoxMeUp for PanicPayload { - fn box_me_up(&mut self) -> *mut (dyn Any + Send) { + fn take_box(&mut self) -> *mut (dyn Any + Send) { let data = match self.inner.take() { Some(a) => Box::new(a) as Box, - None => Box::new(()), + None => Box::new(()), // this should never happen: we got called twice }; Box::into_raw(data) } @@ -488,7 +489,7 @@ pub fn update_count_then_panic(msg: Box) -> ! { struct RewrapBox(Box); unsafe impl BoxMeUp for RewrapBox { - fn box_me_up(&mut self) -> *mut (dyn Any + Send) { + fn take_box(&mut self) -> *mut (dyn Any + Send) { Box::into_raw(mem::replace(&mut self.0, Box::new(()))) } From 18bb9129840bc62f083f93d6518a50b4df5bb3b1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Nov 2019 17:24:11 +0100 Subject: [PATCH 07/43] 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 08/43] 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 09/43] 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 10/43] 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 11/43] 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 3c485795517d1f5a6ebfff6368dfae7a7cd85b85 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 25 Nov 2019 12:24:39 +0100 Subject: [PATCH 12/43] more panicking comments --- src/libcore/panicking.rs | 9 +++++---- src/libstd/panicking.rs | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 4833194be37ac..5a8d647396dda 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -11,13 +11,13 @@ //! ``` //! //! This definition allows for panicking with any general message, but it does not -//! allow for failing with a `Box` value. The reason for this is that libcore -//! is not allowed to allocate. +//! allow for failing with a `Box` value. (`PanicInfo` just contains a `&(dyn Any + Send)`, +//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.) +//! The reason for this is that libcore is not allowed to allocate. //! //! This module contains a few other panicking functions, but these are just the //! necessary lang items for the compiler. All panics are funneled through this -//! one function. Currently, the actual symbol is declared in the standard -//! library, but the location of this may change over time. +//! one function. The actual symbol is declared through the `#[panic_handler]` attribute. // ignore-tidy-undocumented-unsafe @@ -72,6 +72,7 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! { } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index a16eec45b9aa1..cb035f48d90f4 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -455,7 +455,9 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, match HOOK { // Some platforms know that printing to stderr won't ever actually // print anything, and if that's the case we can skip the default - // hook. + // hook. Since string formatting happens lazily when calling `payload` + // methods, this means that with libpanic_abort, we don't format + // the string at all! Hook::Default if panic_output().is_none() => {} Hook::Default => { info.set_payload(payload.get()); From 3a8e1b63cfc472a3c4884f6a31ab2236d7dd2fb7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Nov 2019 08:18:57 +0100 Subject: [PATCH 13/43] panic_handler -> begin_panic_handler (and more comments) --- src/libstd/panicking.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index cb035f48d90f4..31dcbc6a7cbda 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -316,16 +316,17 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>, unsafe { intrinsics::abort() } } + // Just package everything into a `PanicInfo` and continue like libcore panics. let (file, line, col) = *file_line_col; let location = Location::internal_constructor(file, line, col); let info = PanicInfo::internal_constructor(Some(msg), &location); - panic_handler(&info) + begin_panic_handler(&info) } -/// Entry point of panic from the libcore crate (`panic_impl` lang item). +/// Entry point of panics from the libcore crate (`panic_impl` lang item). #[cfg_attr(not(test), panic_handler)] #[unwind(allowed)] -fn panic_handler(info: &PanicInfo<'_>) -> ! { +pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct PanicPayload<'a> { inner: &'a fmt::Arguments<'a>, string: Option, @@ -374,7 +375,9 @@ fn panic_handler(info: &PanicInfo<'_>) -> ! { &file_line_col); } -/// This is the entry point of panicking for panic!() and assert!(). +/// This is the entry point of panicking for the non-format-string variants of +/// panic!() and assert!(). In particular, this is the only entry point that supports +/// arbitrary payloads, not just format strings. #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "0")] From 3e96ca2bf7f7c558623e372e7a9800ac752faa9c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Nov 2019 09:24:39 +0100 Subject: [PATCH 14/43] abort on BoxMeUp misuse --- src/libcore/panic.rs | 8 ++++++++ src/libstd/panicking.rs | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 0abc481f6e53b..99b372d92c8b6 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -266,8 +266,16 @@ impl fmt::Display for Location<'_> { #[unstable(feature = "std_internals", issue = "0")] #[doc(hidden)] pub unsafe trait BoxMeUp { + /// Take full ownership of the contents. /// The return type is actually `Box`, but we cannot use `Box` in libcore. + /// /// After this method got called, only some dummy default value is left in `self`. + /// Calling this method twice, or calling `get` after calling this method, is an error. + /// + /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only + /// gets a borrowed `dyn BoxMeUp`. fn take_box(&mut self) -> *mut (dyn Any + Send); + + /// Just borrow the contents. fn get(&mut self) -> &(dyn Any + Send); } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 31dcbc6a7cbda..5ba5d89bb63b9 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -20,6 +20,7 @@ use crate::sys_common::rwlock::RWLock; use crate::sys_common::{thread_info, util}; use crate::sys_common::backtrace::{self, RustBacktrace}; use crate::thread; +use crate::process; #[cfg(not(test))] use crate::io::set_panic; @@ -414,7 +415,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 fn take_box(&mut self) -> *mut (dyn Any + Send) { let data = match self.inner.take() { Some(a) => Box::new(a) as Box, - None => Box::new(()), // this should never happen: we got called twice + None => process::abort(), }; Box::into_raw(data) } @@ -422,7 +423,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 fn get(&mut self) -> &(dyn Any + Send) { match self.inner { Some(ref a) => a, - None => &(), + None => process::abort(), } } } From 61486f4de3b5e04f401a4da2edae2fc4c9f02bc7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Nov 2019 09:27:11 +0100 Subject: [PATCH 15/43] expand comment --- src/libstd/panicking.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 5ba5d89bb63b9..8f9a4c05b5702 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -457,11 +457,12 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, let mut info = PanicInfo::internal_constructor(message, &location); HOOK_LOCK.read(); match HOOK { - // Some platforms know that printing to stderr won't ever actually + // Some platforms (like wasm) know that printing to stderr won't ever actually // print anything, and if that's the case we can skip the default // hook. Since string formatting happens lazily when calling `payload` - // methods, this means that with libpanic_abort, we don't format - // the string at all! + // methods, this means we avoid formatting the string at all! + // (The panic runtime might still call `payload.take_box()` though and trigger + // formatting.) Hook::Default if panic_output().is_none() => {} Hook::Default => { info.set_payload(payload.get()); From 4a19ef938c3670afb8cc278d3d31a803b19addab Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Nov 2019 09:29:39 +0100 Subject: [PATCH 16/43] explain why __rust_start_panic does not take a Box --- src/libstd/panicking.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 8f9a4c05b5702..e0d980fc306b5 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -47,6 +47,8 @@ extern { vtable_ptr: *mut usize) -> u32; /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. + /// It cannot be `Box` because the other end of this call does not depend + /// on liballoc, and thus cannot use `Box`. #[unwind(allowed)] fn __rust_start_panic(payload: usize) -> u32; } From babe9fcbc1d5aa5a6a53b7d2e34777cfe28e2c41 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Nov 2019 10:23:15 +0100 Subject: [PATCH 17/43] rename update_count_then_panic -> rust_panic_without_hook --- src/libstd/panic.rs | 2 +- src/libstd/panicking.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index e36496d4c1c0d..cd024068d2d47 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -425,5 +425,5 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// ``` #[stable(feature = "resume_unwind", since = "1.9.0")] pub fn resume_unwind(payload: Box) -> ! { - panicking::update_count_then_panic(payload) + panicking::rust_panic_without_hook(payload) } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index e0d980fc306b5..c028ddcd676fc 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -491,8 +491,9 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, rust_panic(payload) } -/// Shim around rust_panic. Called by resume_unwind. -pub fn update_count_then_panic(msg: Box) -> ! { +/// This is the entry point for `resume_unwind`. +/// It just forwards the payload to the panic runtime. +pub fn rust_panic_without_hook(payload: Box) -> ! { update_panic_count(1); struct RewrapBox(Box); @@ -507,7 +508,7 @@ pub fn update_count_then_panic(msg: Box) -> ! { } } - rust_panic(&mut RewrapBox(msg)) + rust_panic(&mut RewrapBox(payload)) } /// An unmangled function (through `rustc_std_internal_symbol`) on which to slap From 68b1ac98744b8e03bbcc5ab38f3afbd04f1ec097 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 12:16:36 +0100 Subject: [PATCH 18/43] 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 19/43] 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()); From 58a9c73bbd9e115888353aa81ee59ee4862c8cf9 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 22:48:41 +0100 Subject: [PATCH 20/43] Make the HIR map own the Definitions. --- src/librustc/hir/map/mod.rs | 10 +++++----- src/librustc_interface/passes.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) 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_interface/passes.rs b/src/librustc_interface/passes.rs index a745d63426b7a..63ea24d89ff85 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -777,7 +777,7 @@ pub fn create_global_ctxt( // Construct the HIR map. let hir_map = time(sess, "indexing HIR", || { - hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs) + hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, defs) }); let query_result_on_disk_cache = time(sess, "load query result cache", || { From b99513be57bfb21c546b29999fc541a402e27a10 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 22:51:02 +0100 Subject: [PATCH 21/43] Have Queries own the GlobalCtxt. The construction of the GlobalCtxt is moved from a generator's stack to the Queries struct. Since the GlobalCtxt requires the HIR Forest and the arenas to live longer, those are moved into Queries the same way. The resulting handling of objects is more brittle, because consumers of the Once objects need to be careful of their initialisation. --- src/librustc_interface/passes.rs | 56 ++++++++++++------------------- src/librustc_interface/queries.rs | 53 +++++++++++++++++++---------- src/librustdoc/test.rs | 2 +- 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 63ea24d89ff85..99945ebf8c4cf 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -22,7 +22,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}; use rustc_errors::PResult; use rustc_incremental; use rustc_metadata::cstore; @@ -740,44 +740,41 @@ 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 BoxedGlobalCtxt<'tcx>(&'tcx GlobalCtxt<'tcx>); -impl BoxedGlobalCtxt { +impl<'gcx> BoxedGlobalCtxt<'gcx> { pub fn enter(&mut self, f: F) -> R where F: for<'tcx> 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<'gcx>( + compiler: &'gcx Compiler, lint_store: Lrc, - mut hir_forest: hir::map::Forest, + hir_forest: &'gcx hir::map::Forest, mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, -) -> BoxedGlobalCtxt { - let sess = compiler.session().clone(); + global_ctxt: &'gcx Once>, + arenas: &'gcx Once, +) -> BoxedGlobalCtxt<'gcx> { + let sess = &compiler.session(); let codegen_backend = compiler.codegen_backend().clone(); - let crate_name = crate_name.to_string(); 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(); + let arenas = arenas.init_locking(|| 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) + hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) }); let query_result_on_disk_cache = time(sess, "load query result cache", || { @@ -796,7 +793,7 @@ pub fn create_global_ctxt( callback(sess, &mut local_providers, &mut extern_providers); } - let gcx = TyCtxt::create_global_ctxt( + let gcx = global_ctxt.init_locking(move || TyCtxt::create_global_ctxt( sess, lint_store, local_providers, @@ -807,26 +804,15 @@ pub fn create_global_ctxt( query_result_on_disk_cache, &crate_name, &outputs - ); + )); - global_ctxt = Some(gcx); - let gcx = global_ctxt.as_ref().unwrap(); - - ty::tls::enter_global(gcx, |tcx| { + 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)); }); - yield BoxedGlobalCtxt::initial_yield(()); - box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx)); - - if sess.opts.debugging_opts.query_stats { - gcx.queries.print_stats(); - } - }); - - result + BoxedGlobalCtxt(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 3b03cfc12bc11..a90483f8c7104 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -2,7 +2,7 @@ use crate::interface::{Compiler, Result}; use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt}; use rustc_incremental::DepGraphFuture; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Once}; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; @@ -12,7 +12,7 @@ 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; @@ -70,6 +70,9 @@ impl Default for Query { pub struct Queries<'comp> { compiler: &'comp Compiler, + gcx: Once>, + arenas: Once, + forest: Once, dep_graph_future: Query>, parse: Query, @@ -77,9 +80,9 @@ pub struct Queries<'comp> { 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<(&'comp hir::map::Forest, Steal)>, prepare_outputs: Query, - global_ctxt: Query, + global_ctxt: Query>, ongoing_codegen: Query>, } @@ -87,6 +90,9 @@ impl<'comp> Queries<'comp> { pub fn new(compiler: &'comp Compiler) -> Queries<'comp> { Queries { compiler, + gcx: Once::new(), + arenas: Once::new(), + forest: Once::new(), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -209,15 +215,15 @@ impl<'comp> Queries<'comp> { } pub fn lower_to_hir( - &self, - ) -> Result<&Query<(Steal, Steal)>> { + &'comp self, + ) -> Result<&Query<(&'comp 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, @@ -225,7 +231,8 @@ impl<'comp> Queries<'comp> { &*self.dep_graph()?.peek(), &krate ) - })?); + })?; + let hir = self.forest.init_locking(|| hir); Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } @@ -242,25 +249,27 @@ impl<'comp> Queries<'comp> { }) } - pub fn global_ctxt(&self) -> Result<&Query> { + pub fn global_ctxt(&'comp 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.compiler, lint_store, - hir_forest.steal(), + hir_forest, resolver_outputs.steal(), outputs, - &crate_name)) + &crate_name, + &self.gcx, + &self.arenas, + )) }) } - pub fn ongoing_codegen(&self) -> Result<&Query>> { + pub fn ongoing_codegen(&'comp self) -> Result<&Query>> { self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { @@ -278,7 +287,7 @@ impl<'comp> Queries<'comp> { }) } - pub fn linker(&self) -> Result { + pub fn linker(&'comp self) -> Result { let dep_graph = self.dep_graph()?; let prepare_outputs = self.prepare_outputs()?; let ongoing_codegen = self.ongoing_codegen()?; @@ -317,10 +326,18 @@ impl Linker { impl Compiler { pub fn enter(&self, f: F) -> T - where F: FnOnce(&Queries<'_>) -> T + where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T { let queries = Queries::new(&self); - f(&queries) + 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 diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 44d3dac16606b..d09eb0b2fc263 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -88,7 +88,7 @@ pub fn run(options: Options) -> i32 { 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( From 7b71e9a9df06aebe89c162138e03577e18e09d2a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 22:56:05 +0100 Subject: [PATCH 22/43] Formatting. --- src/librustc_interface/passes.rs | 72 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 99945ebf8c4cf..b264f1d3fe70f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -766,51 +766,49 @@ pub fn create_global_ctxt<'gcx>( arenas: &'gcx Once, ) -> BoxedGlobalCtxt<'gcx> { let sess = &compiler.session(); - let codegen_backend = compiler.codegen_backend().clone(); let defs = mem::take(&mut resolver_outputs.definitions); - let override_queries = compiler.override_queries; - - let arenas = arenas.init_locking(|| AllArenas::new()); - // Construct the HIR map. - let hir_map = time(sess, "indexing HIR", || { - hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) - }); + // Construct the HIR map. + let hir_map = time(sess, "indexing HIR", || { + hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) + }); - let query_result_on_disk_cache = time(sess, "load query result cache", || { - rustc_incremental::load_query_result_cache(sess) - }); + 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); + 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 mut extern_providers = local_providers; - default_provide_extern(&mut extern_providers); - codegen_backend.provide_extern(&mut extern_providers); + let mut extern_providers = local_providers; + default_provide_extern(&mut extern_providers); + codegen_backend.provide_extern(&mut extern_providers); - if let Some(callback) = override_queries { - callback(sess, &mut local_providers, &mut extern_providers); - } + let override_queries = compiler.override_queries; + if let Some(callback) = override_queries { + callback(sess, &mut local_providers, &mut extern_providers); + } - let gcx = global_ctxt.init_locking(move || 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 arenas = arenas.init_locking(|| AllArenas::new()); + let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt( + sess, + lint_store, + local_providers, + extern_providers, + &arenas, + resolver_outputs, + hir_map, + query_result_on_disk_cache, + &crate_name, + &outputs + )); - 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)); - }); + // 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)); + }); BoxedGlobalCtxt(gcx) } From 7e72b36299d54eb3e39991c9b2a9cbaeacccda3e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Nov 2019 23:16:48 +0100 Subject: [PATCH 23/43] Move local Arena to Queries. --- src/librustc/ty/context.rs | 5 +++-- src/librustc_interface/passes.rs | 5 ++++- src/librustc_interface/queries.rs | 7 ++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 954565811694f..91afa0153c8b3 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, + local_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: local_arena, interners, dep_graph, prof: s.prof.clone(), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index b264f1d3fe70f..963663e7d0390 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, Once, 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; @@ -764,6 +765,7 @@ pub fn create_global_ctxt<'gcx>( crate_name: &str, global_ctxt: &'gcx Once>, arenas: &'gcx Once, + local_arena: &'gcx WorkerLocal>, ) -> BoxedGlobalCtxt<'gcx> { let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); @@ -798,6 +800,7 @@ pub fn create_global_ctxt<'gcx>( local_providers, extern_providers, &arenas, + local_arena, resolver_outputs, hir_map, query_result_on_disk_cache, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index a90483f8c7104..4e9e476c64b99 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -2,10 +2,11 @@ use crate::interface::{Compiler, Result}; use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt}; use rustc_incremental::DepGraphFuture; -use rustc_data_structures::sync::{Lrc, Once}; +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; @@ -74,6 +75,8 @@ pub struct Queries<'comp> { arenas: Once, forest: Once, + local_arena: WorkerLocal>, + dep_graph_future: Query>, parse: Query, crate_name: Query, @@ -93,6 +96,7 @@ impl<'comp> Queries<'comp> { gcx: Once::new(), arenas: Once::new(), forest: Once::new(), + local_arena: WorkerLocal::new(|_| Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -265,6 +269,7 @@ impl<'comp> Queries<'comp> { &crate_name, &self.gcx, &self.arenas, + &self.local_arena, )) }) } From 1f850f61ead8b6fc05236e5e2514c2b6c9fe34de Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 26 Nov 2019 22:30:54 +0000 Subject: [PATCH 24/43] Record temporary static references in generator witnesses --- src/librustc/ty/util.rs | 17 +++++++++++++++++ src/librustc_mir/hair/cx/expr.rs | 9 +-------- src/librustc_typeck/check/generator_interior.rs | 13 +++++++++++-- .../generator/static-reference-across-yield.rs | 16 ++++++++++++++++ 4 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/generator/static-reference-across-yield.rs diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0c9fbfe664189..0b11a9efd81d7 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -682,6 +682,23 @@ impl<'tcx> TyCtxt<'tcx> { self.static_mutability(def_id) == Some(hir::Mutability::Mutable) } + /// Get the type of the pointer to the static that we use in MIR. + pub fn static_ptr_ty(&self, def_id: DefId) -> Ty<'tcx> { + // Make sure that any constants in the static's type are evaluated. + let static_ty = self.normalize_erasing_regions( + ty::ParamEnv::empty(), + self.type_of(def_id), + ); + + if self.is_mutable_static(def_id) { + self.mk_mut_ptr(static_ty) + } else if self.is_foreign_item(def_id) { + self.mk_imm_ptr(static_ty) + } else { + self.mk_imm_ref(self.lifetimes.re_erased, static_ty) + } + } + /// Expands the given impl trait type, stopping if the type is recursive. pub fn try_expand_impl_trait_type( self, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index afc4e461c0df5..8c852854be1f9 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -933,14 +933,7 @@ fn convert_path_expr<'a, 'tcx>( // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is // a constant reference (or constant raw pointer for `static mut`) in MIR Res::Def(DefKind::Static, id) => { - let ty = cx.tcx.type_of(id); - let ty = if cx.tcx.is_mutable_static(id) { - cx.tcx.mk_mut_ptr(ty) - } else if cx.tcx.is_foreign_item(id) { - cx.tcx.mk_imm_ptr(ty) - } else { - cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_static, ty) - }; + let ty = cx.tcx.static_ptr_ty(id); let ptr = cx.tcx.alloc_map.lock().create_static_alloc(id); let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); ExprKind::Deref { arg: Expr { diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 6e37c0dbbdf9d..fcf6b22f74f3c 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -185,6 +185,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr) { + let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + match &expr.kind { ExprKind::Call(callee, args) => match &callee.kind { ExprKind::Path(qpath) => { @@ -210,13 +212,20 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { } _ => intravisit::walk_expr(self, expr), } + ExprKind::Path(qpath) => { + let res = self.fcx.tables.borrow().qpath_res(qpath, expr.hir_id); + if let Res::Def(DefKind::Static, def_id) = res { + // Statics are lowered to temporary references or + // pointers in MIR, so record that type. + let ptr_ty = self.fcx.tcx.static_ptr_ty(def_id); + self.record(ptr_ty, scope, Some(expr), expr.span); + } + } _ => intravisit::walk_expr(self, expr), } self.expr_count += 1; - let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - // If there are adjustments, then record the final type -- // this is the actual value that is being produced. if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) { diff --git a/src/test/ui/generator/static-reference-across-yield.rs b/src/test/ui/generator/static-reference-across-yield.rs new file mode 100644 index 0000000000000..23b11593bb5d6 --- /dev/null +++ b/src/test/ui/generator/static-reference-across-yield.rs @@ -0,0 +1,16 @@ +// build-pass +#![feature(generators)] + +static A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn main() { + static || { + let u = A[{yield; 1}]; + }; + static || { + match A { + i if { yield; true } => (), + _ => (), + } + }; +} From 79e232401e07c48020b327a947c9d98d0696f082 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Nov 2019 13:13:57 +0100 Subject: [PATCH 25/43] Rename lifetimes. --- src/librustc_interface/passes.rs | 18 +++++++++--------- src/librustc_interface/queries.rs | 26 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 963663e7d0390..d3e29fa111130 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -743,10 +743,10 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { pub struct BoxedGlobalCtxt<'tcx>(&'tcx GlobalCtxt<'tcx>); -impl<'gcx> BoxedGlobalCtxt<'gcx> { +impl<'tcx> BoxedGlobalCtxt<'tcx> { pub fn enter(&mut self, f: F) -> R where - F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R, + F: FnOnce(TyCtxt<'tcx>) -> R, { ty::tls::enter_global(self.0, |tcx| f(tcx)) } @@ -756,17 +756,17 @@ impl<'gcx> BoxedGlobalCtxt<'gcx> { } } -pub fn create_global_ctxt<'gcx>( - compiler: &'gcx Compiler, +pub fn create_global_ctxt<'tcx>( + compiler: &'tcx Compiler, lint_store: Lrc, - hir_forest: &'gcx hir::map::Forest, + hir_forest: &'tcx hir::map::Forest, mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, - global_ctxt: &'gcx Once>, - arenas: &'gcx Once, - local_arena: &'gcx WorkerLocal>, -) -> BoxedGlobalCtxt<'gcx> { + global_ctxt: &'tcx Once>, + arenas: &'tcx Once, + local_arena: &'tcx WorkerLocal>, +) -> BoxedGlobalCtxt<'tcx> { let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 4e9e476c64b99..04bf04189bd46 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -69,13 +69,13 @@ impl Default for Query { } } -pub struct Queries<'comp> { - compiler: &'comp Compiler, - gcx: Once>, +pub struct Queries<'tcx> { + compiler: &'tcx Compiler, + gcx: Once>, arenas: Once, forest: Once, - local_arena: WorkerLocal>, + local_arena: WorkerLocal>, dep_graph_future: Query>, parse: Query, @@ -83,14 +83,14 @@ pub struct Queries<'comp> { register_plugins: Query<(ast::Crate, Lrc)>, expansion: Query<(ast::Crate, Steal>>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(&'comp hir::map::Forest, Steal)>, + lower_to_hir: Query<(&'tcx hir::map::Forest, Steal)>, prepare_outputs: Query, - global_ctxt: Query>, + global_ctxt: Query>, ongoing_codegen: Query>, } -impl<'comp> Queries<'comp> { - pub fn new(compiler: &'comp Compiler) -> Queries<'comp> { +impl<'tcx> Queries<'tcx> { + pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> { Queries { compiler, gcx: Once::new(), @@ -219,8 +219,8 @@ impl<'comp> Queries<'comp> { } pub fn lower_to_hir( - &'comp self, - ) -> Result<&Query<(&'comp hir::map::Forest, Steal)>> { + &'tcx self, + ) -> Result<&Query<(&'tcx hir::map::Forest, Steal)>> { self.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); @@ -253,7 +253,7 @@ impl<'comp> Queries<'comp> { }) } - pub fn global_ctxt(&'comp self) -> Result<&Query>> { + 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(); @@ -274,7 +274,7 @@ impl<'comp> Queries<'comp> { }) } - pub fn ongoing_codegen(&'comp self) -> Result<&Query>> { + pub fn ongoing_codegen(&'tcx self) -> Result<&Query>> { self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { @@ -292,7 +292,7 @@ impl<'comp> Queries<'comp> { }) } - pub fn linker(&'comp self) -> Result { + pub fn linker(&'tcx self) -> Result { let dep_graph = self.dep_graph()?; let prepare_outputs = self.prepare_outputs()?; let ongoing_codegen = self.ongoing_codegen()?; From e5ed1010987c21a4a5d4ea4e46aebf7adc872bfc Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Nov 2019 13:17:58 +0100 Subject: [PATCH 26/43] Rename BoxedGlobalCtxt. --- src/librustc_interface/passes.rs | 8 ++++---- src/librustc_interface/queries.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index d3e29fa111130..d2bb2cdfaffac 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -741,9 +741,9 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { rustc_codegen_ssa::provide_extern(providers); } -pub struct BoxedGlobalCtxt<'tcx>(&'tcx GlobalCtxt<'tcx>); +pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>); -impl<'tcx> BoxedGlobalCtxt<'tcx> { +impl<'tcx> QueryContext<'tcx> { pub fn enter(&mut self, f: F) -> R where F: FnOnce(TyCtxt<'tcx>) -> R, @@ -766,7 +766,7 @@ pub fn create_global_ctxt<'tcx>( global_ctxt: &'tcx Once>, arenas: &'tcx Once, local_arena: &'tcx WorkerLocal>, -) -> BoxedGlobalCtxt<'tcx> { +) -> QueryContext<'tcx> { let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); @@ -813,7 +813,7 @@ pub fn create_global_ctxt<'tcx>( time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); }); - BoxedGlobalCtxt(gcx) + 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 04bf04189bd46..581ebe9c00fe1 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,5 +1,5 @@ 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, Once, WorkerLocal}; @@ -85,7 +85,7 @@ pub struct Queries<'tcx> { dep_graph: Query, lower_to_hir: Query<(&'tcx hir::map::Forest, Steal)>, prepare_outputs: Query, - global_ctxt: Query>, + global_ctxt: Query>, ongoing_codegen: Query>, } @@ -253,7 +253,7 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn global_ctxt(&'tcx self) -> Result<&Query>> { + 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(); From 77a4c85e54401e06ea0cc8539a183ab8d08fa005 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Nov 2019 13:19:33 +0100 Subject: [PATCH 27/43] Simplify handling of AllArenas. --- src/librustc_interface/passes.rs | 5 ++--- src/librustc_interface/queries.rs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index d2bb2cdfaffac..66666a027c0d5 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -764,7 +764,7 @@ pub fn create_global_ctxt<'tcx>( outputs: OutputFilenames, crate_name: &str, global_ctxt: &'tcx Once>, - arenas: &'tcx Once, + all_arenas: &'tcx AllArenas, local_arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { let sess = &compiler.session(); @@ -793,13 +793,12 @@ pub fn create_global_ctxt<'tcx>( callback(sess, &mut local_providers, &mut extern_providers); } - let arenas = arenas.init_locking(|| AllArenas::new()); let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt( sess, lint_store, local_providers, extern_providers, - &arenas, + &all_arenas, local_arena, resolver_outputs, hir_map, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 581ebe9c00fe1..7e8ba9f270258 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -72,9 +72,9 @@ impl Default for Query { pub struct Queries<'tcx> { compiler: &'tcx Compiler, gcx: Once>, - arenas: Once, forest: Once, + all_arenas: AllArenas, local_arena: WorkerLocal>, dep_graph_future: Query>, @@ -94,8 +94,8 @@ impl<'tcx> Queries<'tcx> { Queries { compiler, gcx: Once::new(), - arenas: Once::new(), forest: Once::new(), + all_arenas: AllArenas::new(), local_arena: WorkerLocal::new(|_| Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), @@ -268,7 +268,7 @@ impl<'tcx> Queries<'tcx> { outputs, &crate_name, &self.gcx, - &self.arenas, + &self.all_arenas, &self.local_arena, )) }) From e321ba989c9f03748d5c19aead84edfcc9e9e69a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Nov 2019 13:24:19 +0100 Subject: [PATCH 28/43] Misc renames. --- src/librustc/ty/context.rs | 4 ++-- src/librustc_interface/passes.rs | 7 +++---- src/librustc_interface/queries.rs | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 91afa0153c8b3..3c1cfa3f79f37 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1170,7 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> { local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, - local_arena: &'tcx WorkerLocal>, + arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, @@ -1226,7 +1226,7 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, cstore, - arena: local_arena, + arena, interners, dep_graph, prof: s.prof.clone(), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 66666a027c0d5..1df84ce0b7394 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -765,7 +765,7 @@ pub fn create_global_ctxt<'tcx>( crate_name: &str, global_ctxt: &'tcx Once>, all_arenas: &'tcx AllArenas, - local_arena: &'tcx WorkerLocal>, + arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); @@ -788,8 +788,7 @@ pub fn create_global_ctxt<'tcx>( default_provide_extern(&mut extern_providers); codegen_backend.provide_extern(&mut extern_providers); - let override_queries = compiler.override_queries; - if let Some(callback) = override_queries { + if let Some(callback) = compiler.override_queries { callback(sess, &mut local_providers, &mut extern_providers); } @@ -799,7 +798,7 @@ pub fn create_global_ctxt<'tcx>( local_providers, extern_providers, &all_arenas, - local_arena, + arena, resolver_outputs, hir_map, query_result_on_disk_cache, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 7e8ba9f270258..53ab5eb990ddf 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -75,7 +75,7 @@ pub struct Queries<'tcx> { forest: Once, all_arenas: AllArenas, - local_arena: WorkerLocal>, + arena: WorkerLocal>, dep_graph_future: Query>, parse: Query, @@ -96,7 +96,7 @@ impl<'tcx> Queries<'tcx> { gcx: Once::new(), forest: Once::new(), all_arenas: AllArenas::new(), - local_arena: WorkerLocal::new(|_| Arena::default()), + arena: WorkerLocal::new(|_| Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -269,7 +269,7 @@ impl<'tcx> Queries<'tcx> { &crate_name, &self.gcx, &self.all_arenas, - &self.local_arena, + &self.arena, )) }) } From 1e12f39d83eeddd523e384e20ab4f1fa56eb8888 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Nov 2019 13:32:28 +0100 Subject: [PATCH 29/43] Allocate HIR Forest on arena. --- src/librustc/arena.rs | 1 + src/librustc_interface/queries.rs | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) 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_interface/queries.rs b/src/librustc_interface/queries.rs index 53ab5eb990ddf..6103d42c5dbcb 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -72,7 +72,6 @@ impl Default for Query { pub struct Queries<'tcx> { compiler: &'tcx Compiler, gcx: Once>, - forest: Once, all_arenas: AllArenas, arena: WorkerLocal>, @@ -94,7 +93,6 @@ impl<'tcx> Queries<'tcx> { Queries { compiler, gcx: Once::new(), - forest: Once::new(), all_arenas: AllArenas::new(), arena: WorkerLocal::new(|_| Arena::default()), dep_graph_future: Default::default(), @@ -236,7 +234,7 @@ impl<'tcx> Queries<'tcx> { &krate ) })?; - let hir = self.forest.init_locking(|| hir); + let hir = self.arena.alloc(hir); Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } From 38f9cd4d696a729dcf832a62af0f2eb43908bafb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Nov 2019 13:51:38 +0100 Subject: [PATCH 30/43] Clean up E0080 long explanation --- src/librustc_error_codes/error_codes/E0080.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0080.md b/src/librustc_error_codes/error_codes/E0080.md index 262bf00d38540..273238a943b4f 100644 --- a/src/librustc_error_codes/error_codes/E0080.md +++ b/src/librustc_error_codes/error_codes/E0080.md @@ -1,14 +1,18 @@ -This error indicates that the compiler was unable to sensibly evaluate a -constant expression that had to be evaluated. Attempting to divide by 0 -or causing integer overflow are two ways to induce this error. For example: +A constant value failed to get evaluated. + +Erroneous code example: ```compile_fail,E0080 enum Enum { X = (1 << 500), - Y = (1 / 0) + Y = (1 / 0), } ``` +This error indicates that the compiler was unable to sensibly evaluate a +constant expression that had to be evaluated. Attempting to divide by 0 +or causing an integer overflow are two ways to induce this error. + Ensure that the expressions given can be evaluated as the desired integer type. See the FFI section of the Reference for more information about using a custom integer type: From ce696101c492964c31d5f368b27e6f2027af8f07 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Nov 2019 13:51:44 +0100 Subject: [PATCH 31/43] Clean up E0081 long explanation --- src/librustc_error_codes/error_codes/E0081.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0081.md b/src/librustc_error_codes/error_codes/E0081.md index ec88ca9765e29..fd5eca68e21fd 100644 --- a/src/librustc_error_codes/error_codes/E0081.md +++ b/src/librustc_error_codes/error_codes/E0081.md @@ -1,21 +1,23 @@ -Enum discriminants are used to differentiate enum variants stored in memory. -This error indicates that the same value was used for two or more variants, -making them impossible to tell apart. +A discrimant value is present more than once. + +Erroneous code example: ```compile_fail,E0081 -// Bad. enum Enum { P = 3, - X = 3, + X = 3, // error! Y = 5, } ``` +Enum discriminants are used to differentiate enum variants stored in memory. +This error indicates that the same value was used for two or more variants, +making it impossible to distinguish them. + ``` -// Good. enum Enum { P, - X = 3, + X = 3, // ok! Y = 5, } ``` @@ -27,7 +29,7 @@ variants. ```compile_fail,E0081 enum Bad { X, - Y = 0 + Y = 0, // error! } ``` From 7edaebaf6ab309bd4730988ac5978c42a9159fea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Nov 2019 13:51:50 +0100 Subject: [PATCH 32/43] Clean up E0091 long explanation --- src/librustc_error_codes/error_codes/E0091.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0091.md b/src/librustc_error_codes/error_codes/E0091.md index 2a092402429f1..03cb32803715e 100644 --- a/src/librustc_error_codes/error_codes/E0091.md +++ b/src/librustc_error_codes/error_codes/E0091.md @@ -1,5 +1,6 @@ -You gave an unnecessary type or const parameter in a type alias. Erroneous -code example: +An unnecessary type or const parameter was given in a type alias. + +Erroneous code example: ```compile_fail,E0091 type Foo = u32; // error: type parameter `T` is unused From d411dd27bf391ca8da15a43341ad519a741b2e2a Mon Sep 17 00:00:00 2001 From: CreepySkeleton Date: Wed, 13 Nov 2019 20:43:45 +0300 Subject: [PATCH 33/43] Elaborate on std::ptr::{as_ref,as_mod} and clarify docs --- src/libcore/ptr/mod.rs | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 39d56958f5de0..21314d429c6da 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -1074,17 +1074,22 @@ impl *const T { /// operation because the returned value could be pointing to invalid /// memory. /// - /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole - /// size of `T`) and points to an initialized instance of `T`. This applies - /// even if the result of this method is unused! + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// - it is properly aligned + /// - it must point to an initialized instance of T; in particular, the pointer must be + /// "dereferencable" in the sense defined [here]. + /// + /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is, the only safe approach is to ensure that they are indeed initialized.) /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. It is up to the - /// caller to ensure that for the duration of this lifetime, the memory this - /// pointer points to does not get written to outside of `UnsafeCell`. + /// not necessarily reflect the actual lifetime of the data. *You* must enforce + /// Rust's aliasing rules. In particular, for the duration of this lifetime, + /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`). + /// + /// [here]: https://doc.rust-lang.org/std/ptr/index.html#safety /// /// # Examples /// @@ -1929,18 +1934,23 @@ impl *mut T { /// of the returned pointer, nor can it ensure that the lifetime `'a` /// returned is indeed a valid lifetime for the contained data. /// - /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole - /// size of `T`) and points to an initialized instance of `T`. This applies - /// even if the result of this method is unused! + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// - it is properly aligned + /// - it must point to an initialized instance of T; in particular, the pointer must be + /// "dereferencable" in the sense defined [here]. + /// + /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is the only safe approach is to ensure that they are indeed initialized.) /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. It is up to the - /// caller to ensure that for the duration of this lifetime, the memory this - /// pointer points to does not get accessed through any other pointer. + /// not necessarily reflect the actual lifetime of the data. *You* must enforce + /// Rust's aliasing rules. In particular, for the duration of this lifetime, + /// the memory this pointer points to must not get accessed (read or written) + /// through any other pointer. /// + /// [here]: https://doc.rust-lang.org/std/ptr/index.html#safety /// [`as_ref`]: #method.as_ref /// /// # Examples From f11dd32f751b4a64bea0bdd0020879caec197d3f Mon Sep 17 00:00:00 2001 From: CreepySkeleton Date: Wed, 27 Nov 2019 21:36:09 +0300 Subject: [PATCH 34/43] Use intra-doc links --- src/libcore/ptr/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 21314d429c6da..1e051dbebcaf8 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -1089,7 +1089,7 @@ impl *const T { /// Rust's aliasing rules. In particular, for the duration of this lifetime, /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`). /// - /// [here]: https://doc.rust-lang.org/std/ptr/index.html#safety + /// [here]: crate::ptr#safety /// /// # Examples /// @@ -1950,7 +1950,7 @@ impl *mut T { /// the memory this pointer points to must not get accessed (read or written) /// through any other pointer. /// - /// [here]: https://doc.rust-lang.org/std/ptr/index.html#safety + /// [here]: crate::ptr#safety /// [`as_ref`]: #method.as_ref /// /// # Examples From 59d73912387724933511c32306da038db545ea66 Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Wed, 20 Nov 2019 23:17:30 +0100 Subject: [PATCH 35/43] Draw vertical lines in compiler error messages with multiline annotations correctly when non-1space unicode characters are to the left For this we use the correct calculation of the 'left' identation --- src/librustc_errors/emitter.rs | 6 +++--- .../non-1-width-unicode-multiline-label.rs | 7 +++++++ .../non-1-width-unicode-multiline-label.stderr | 17 +++++++++++++++++ .../non-whitespace-trimming-unicode.stderr | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs create mode 100644 src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index ea779982ba961..451913757482a 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -835,7 +835,7 @@ impl EmitterWriter { return vec![]; } - // Write the colunmn separator. + // Write the column separator. // // After this we will have: // @@ -906,7 +906,7 @@ impl EmitterWriter { // | __________ // | | | // | | - // 3 | + // 3 | | // 4 | | } // | |_ for &(pos, annotation) in &annotations_position { @@ -920,7 +920,7 @@ impl EmitterWriter { if pos > 1 && (annotation.has_label() || annotation.takes_space()) { for p in line_offset + 1..=line_offset + pos { buffer.putc(p, - code_offset + annotation.start_col - margin.computed_left, + (code_offset + annotation.start_col).saturating_sub(left), '|', style); } diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs new file mode 100644 index 0000000000000..cc94680530cf2 --- /dev/null +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs @@ -0,0 +1,7 @@ +// ignore-tidy-linelength + +fn main() { + let unicode_is_fun = "؁‱ஹ௸௵꧄.ဪ꧅⸻𒈙𒐫﷽𒌄𒈟𒍼𒁎𒀱𒌧𒅃 𒈓𒍙𒊎𒄡𒅌𒁏𒀰𒐪𒐩𒈙𒐫𪚥"; + let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + //~^ ERROR binary operation `+` cannot be applied to type `&str` +} diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr new file mode 100644 index 0000000000000..9f0f990670f2d --- /dev/null +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -0,0 +1,17 @@ +error[E0369]: binary operation `+` cannot be applied to type `&str` + --> $DIR/non-1-width-unicode-multiline-label.rs:5:260 + | +LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇...࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | +help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + | +LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr index d4993fad15c97..1e5ff9398321f 100644 --- a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr +++ b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr @@ -3,7 +3,7 @@ error[E0308]: mismatched types | LL | ...♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂♃♄... | -- ^^ expected `()`, found integer - | | + | | | expected due to this error: aborting due to previous error From df625bdc26b0bccd6390fe22f0fc112e511667f4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 27 Nov 2019 19:02:13 +0000 Subject: [PATCH 36/43] Add async fn test for #66695 --- .../issues/issue-66695-static-refs.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/ui/async-await/issues/issue-66695-static-refs.rs diff --git a/src/test/ui/async-await/issues/issue-66695-static-refs.rs b/src/test/ui/async-await/issues/issue-66695-static-refs.rs new file mode 100644 index 0000000000000..f0609713b4ddc --- /dev/null +++ b/src/test/ui/async-await/issues/issue-66695-static-refs.rs @@ -0,0 +1,24 @@ +// build-pass +// edition:2018 + +static A: [i32; 5] = [1, 2, 3, 4, 5]; + +async fn fun() { + let u = A[async { 1 }.await]; + match A { + i if async { true }.await => (), + _ => (), + } +} + +fn main() { + async { + let u = A[async { 1 }.await]; + }; + async { + match A { + i if async { true }.await => (), + _ => (), + } + }; +} From 9b78191e0812a5d9894746a25fa204a359f2923b Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Wed, 27 Nov 2019 17:17:02 -0500 Subject: [PATCH 37/43] Clarifies how to tag users for assigning PRs --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd1d49fb24dc3..242bae9065a4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -150,13 +150,13 @@ All pull requests are reviewed by another person. We have a bot, request. If you want to request that a specific person reviews your pull request, -you can add an `r?` to the message. For example, [Steve][steveklabnik] usually reviews +you can add an `r?` to the pull request message. For example, [Steve][steveklabnik] usually reviews documentation changes. So if you were to make a documentation change, add r? @steveklabnik -to the end of the message, and @rust-highfive will assign [@steveklabnik][steveklabnik] instead -of a random person. This is entirely optional. +to the end of the pull request message, and [@rust-highfive][rust-highfive] will assign +[@steveklabnik][steveklabnik] instead of a random person. This is entirely optional. After someone has reviewed your pull request, they will leave an annotation on the pull request with an `r+`. It will look something like this: From 2a7dc5ec7f6979ee31e0ec30fbf9b6086e03ca74 Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Thu, 28 Nov 2019 01:23:39 +0100 Subject: [PATCH 38/43] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 242bae9065a4c..54ef0596198f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -150,7 +150,7 @@ All pull requests are reviewed by another person. We have a bot, request. If you want to request that a specific person reviews your pull request, -you can add an `r?` to the pull request message. For example, [Steve][steveklabnik] usually reviews +you can add an `r?` to the pull request description. For example, [Steve][steveklabnik] usually reviews documentation changes. So if you were to make a documentation change, add r? @steveklabnik From 77f2ac4a4981e800708fb5e877817f4781e7f87a Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Thu, 28 Nov 2019 01:26:45 +0100 Subject: [PATCH 39/43] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54ef0596198f1..8fbbd7c4a2e49 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -155,7 +155,7 @@ documentation changes. So if you were to make a documentation change, add r? @steveklabnik -to the end of the pull request message, and [@rust-highfive][rust-highfive] will assign +to the end of the pull request description, and [@rust-highfive][rust-highfive] will assign [@steveklabnik][steveklabnik] instead of a random person. This is entirely optional. After someone has reviewed your pull request, they will leave an annotation From 85a468b8cfc8957c337b426b618dd84984967c3b Mon Sep 17 00:00:00 2001 From: Ohad Ravid Date: Thu, 28 Nov 2019 13:49:58 +0100 Subject: [PATCH 40/43] Clarify `{f32,f64}::EPSILON` docs --- src/libcore/num/f32.rs | 2 +- src/libcore/num/f64.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 38b3fab6d7535..913c0f96d118d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -26,7 +26,7 @@ pub const DIGITS: u32 = 6; /// [Machine epsilon] value for `f32`. /// -/// This is the difference between `1.0` and the next largest representable number. +/// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index f093bae9590ea..6ca830b1f38af 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -26,7 +26,7 @@ pub const DIGITS: u32 = 15; /// [Machine epsilon] value for `f64`. /// -/// This is the difference between `1.0` and the next largest representable number. +/// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon #[stable(feature = "rust1", since = "1.0.0")] From 3048d7e5b54eb75c8a784e0270767436ec070729 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Nov 2019 19:15:32 +0100 Subject: [PATCH 41/43] do not consider memory allocated by caller_location leaked --- src/librustc_mir/interpret/intern.rs | 2 +- .../interpret/intrinsics/caller_location.rs | 2 +- src/librustc_mir/interpret/memory.rs | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 630f3f603449b..f9cb40ffe9446 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -100,7 +100,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // This match is just a canary for future changes to `MemoryKind`, which most likely need // changes in this function. match kind { - MemoryKind::Stack | MemoryKind::Vtable => {}, + MemoryKind::Stack | MemoryKind::Vtable | MemoryKind::CallerLocation => {}, } // Set allocation mutability as appropriate. This is used by LLVM to put things into // read-only memory, and also by Miri when evluating other constants/statics that diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 88bfcd63129fa..9e07a3f1072c1 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -28,7 +28,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let file = Scalar::Ptr(self.tag_static_base_pointer(file_ptr)); let file_len = Scalar::from_uint(filename.as_str().len() as u128, ptr_size); - let location = self.allocate(loc_layout, MemoryKind::Stack); + let location = self.allocate(loc_layout, MemoryKind::CallerLocation); let file_out = self.mplace_field(location, 0)?; let file_ptr_out = self.force_ptr(self.mplace_field(file_out, 0)?.ptr)?; diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index eccdc5b03261b..a8011f7abb14f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -24,11 +24,13 @@ use super::{ #[derive(Debug, PartialEq, Copy, Clone)] pub enum MemoryKind { - /// Error if deallocated except during a stack pop + /// Stack memory. Error if deallocated except during a stack pop. Stack, - /// Error if ever deallocated + /// Memory backing vtables. Error if ever deallocated. Vtable, - /// Additional memory kinds a machine wishes to distinguish from the builtin ones + /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated. + CallerLocation, + /// Additional memory kinds a machine wishes to distinguish from the builtin ones. Machine(T), } @@ -38,6 +40,7 @@ impl MayLeak for MemoryKind { match self { MemoryKind::Stack => false, MemoryKind::Vtable => true, + MemoryKind::CallerLocation => true, MemoryKind::Machine(k) => k.may_leak() } } @@ -719,6 +722,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let extra = match kind { MemoryKind::Stack => " (stack)".to_owned(), MemoryKind::Vtable => " (vtable)".to_owned(), + MemoryKind::CallerLocation => " (caller_location)".to_owned(), MemoryKind::Machine(m) => format!(" ({:?})", m), }; self.dump_alloc_helper( From f07bd0613790080225cc7f7cc735655dcb2257f8 Mon Sep 17 00:00:00 2001 From: Mikhail Babenko Date: Thu, 21 Nov 2019 21:01:14 +0300 Subject: [PATCH 42/43] allow customising ty::TraitRef's printing behavior fix clippy allow customising ty::TraitRef's printing behavior fix clippy stylistic fix --- src/librustc/infer/error_reporting/mod.rs | 16 ++++++- .../nice_region_error/placeholder_error.rs | 8 ++-- src/librustc/infer/mod.rs | 2 +- src/librustc/lint/context.rs | 9 +++- src/librustc/traits/error_reporting.rs | 18 ++++---- src/librustc/traits/select.rs | 4 +- src/librustc/traits/specialize/mod.rs | 2 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/ty/print/pretty.rs | 42 ++++++++++++++++--- src/librustc/ty/structural_impls.rs | 5 +-- src/librustc_privacy/lib.rs | 2 +- src/librustc_typeck/astconv.rs | 12 ++++-- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 6 +-- src/librustc_typeck/coherence/unsafety.rs | 4 +- 15 files changed, 92 insertions(+), 42 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b670658a10a50..5a940f2f80aa2 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1545,8 +1545,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found), infer::Regions(ref exp_found) => self.expected_found_str(exp_found), infer::Consts(ref exp_found) => self.expected_found_str(exp_found), - infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found), - infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found), + infer::TraitRefs(ref exp_found) => { + let pretty_exp_found = ty::error::ExpectedFound { + expected: exp_found.expected.print_only_trait_path(), + found: exp_found.found.print_only_trait_path() + }; + self.expected_found_str(&pretty_exp_found) + }, + infer::PolyTraitRefs(ref exp_found) => { + let pretty_exp_found = ty::error::ExpectedFound { + expected: exp_found.expected.print_only_trait_path(), + found: exp_found.found.print_only_trait_path() + }; + self.expected_found_str(&pretty_exp_found) + }, } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index bfa8353ca343f..3b4d06aab27ef 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -401,7 +401,7 @@ impl NiceRegionError<'me, 'tcx> { format!( "{}`{}` would have to be implemented for the type `{}`", if leading_ellipsis { "..." } else { "" }, - expected_trait_ref, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), expected_trait_ref.map(|tr| tr.self_ty()), ) } else { @@ -409,7 +409,7 @@ impl NiceRegionError<'me, 'tcx> { "{}`{}` must implement `{}`", if leading_ellipsis { "..." } else { "" }, expected_trait_ref.map(|tr| tr.self_ty()), - expected_trait_ref, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) }; @@ -449,14 +449,14 @@ impl NiceRegionError<'me, 'tcx> { let mut note = if passive_voice { format!( "...but `{}` is actually implemented for the type `{}`", - actual_trait_ref, + actual_trait_ref.map(|tr| tr.print_only_trait_path()), actual_trait_ref.map(|tr| tr.self_ty()), ) } else { format!( "...but `{}` actually implements `{}`", actual_trait_ref.map(|tr| tr.self_ty()), - actual_trait_ref, + actual_trait_ref.map(|tr| tr.print_only_trait_path()), ) }; diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 5e204d83aef20..b3ddffc8b12f1 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1292,7 +1292,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String { - self.resolve_vars_if_possible(t).to_string() + self.resolve_vars_if_possible(t).print_only_trait_path().to_string() } /// If `TyVar(vid)` resolves to a type, return that type. Else, return the diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2f865f1f8b501..05543f1d2ef73 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -800,8 +800,13 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { // This shouldn't ever be needed, but just in case: path.push(match trait_ref { Some(trait_ref) => { - Symbol::intern(&format!("", trait_ref, - self_ty)) + Symbol::intern( + &format!( + "", + trait_ref.print_only_trait_path(), + self_ty + ) + ) }, None => Symbol::intern(&format!("", self_ty)), }); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6e723cdc999b0..90db1fe319556 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -737,7 +737,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let is_try = self.tcx.sess.source_map().span_to_snippet(span) .map(|s| &s == "?") .unwrap_or(false); - let is_from = format!("{}", trait_ref).starts_with("std::convert::From<"); + let is_from = + format!("{}", trait_ref.print_only_trait_path()) + .starts_with("std::convert::From<"); let (message, note) = if is_try && is_from { (Some(format!( "`?` couldn't convert the error to `{}`", @@ -768,7 +770,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!( "{}the trait `{}` is not implemented for `{}`", pre_message, - trait_ref, + trait_ref.print_only_trait_path(), trait_ref.self_ty(), ) }; @@ -1189,7 +1191,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if param_ty => { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = trait_ref.to_string(); + let constraint = trait_ref.print_only_trait_path().to_string(); if suggest_constraining_type_param( generics, &mut err, @@ -1416,7 +1418,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", found, - obligation.parent_trait_ref.skip_binder(), + obligation.parent_trait_ref.skip_binder().print_only_trait_path(), ); if has_custom_message { err.note(&msg); @@ -1430,7 +1432,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } err.span_label(span, &format!( "expected an implementor of trait `{}`", - obligation.parent_trait_ref.skip_binder(), + obligation.parent_trait_ref.skip_binder().print_only_trait_path(), )); err.span_suggestion( span, @@ -1562,7 +1564,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } else { err.note(&format!( "`{}` is implemented for `{:?}`, but not for `{:?}`", - trait_ref, + trait_ref.print_only_trait_path(), trait_type, trait_ref.skip_binder().self_ty(), )); @@ -2226,7 +2228,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_note(span, &format!( "future does not implement `{}` as this value is used across an await", - trait_ref, + trait_ref.print_only_trait_path(), )); // Add a note for the item obligation that remains - normally a note pointing to the @@ -2409,7 +2411,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); err.note( &format!("required because of the requirements on the impl of `{}` for `{}`", - parent_trait_ref, + parent_trait_ref.print_only_trait_path(), parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); self.note_obligation_cause_code(err, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 283fa56d11f4f..5f324527a2725 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1044,7 +1044,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); let cause = IntercrateAmbiguityCause::DownstreamCrate { - trait_desc: trait_ref.to_string(), + trait_desc: trait_ref.print_only_trait_path().to_string(), self_desc: if self_ty.has_concrete_skeleton() { Some(self_ty.to_string()) } else { @@ -1386,7 +1386,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !candidate_set.ambiguous && no_candidates_apply { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); - let trait_desc = trait_ref.to_string(); + let trait_desc = trait_ref.print_only_trait_path().to_string(); let self_desc = if self_ty.has_concrete_skeleton() { Some(self_ty.to_string()) } else { diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 475037f54ba38..88a2db3dc6223 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -417,7 +417,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option w.push('>'); } - write!(w, " {} for {}", trait_ref, tcx.type_of(impl_def_id)).unwrap(); + write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap(); // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index d945c756f6662..b8ddf6078bda6 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -146,7 +146,7 @@ impl<'tcx> Children { let self_ty = trait_ref.self_ty(); OverlapError { with_impl: possible_sibling, - trait_desc: trait_ref.to_string(), + trait_desc: trait_ref.print_only_trait_path().to_string(), // Only report the `Self` type if it has at least // some outer concrete shell; otherwise, it's // not adding much information. diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 2a311ea962424..c941b3e5e4be9 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -449,7 +449,7 @@ pub trait PrettyPrinter<'tcx>: p!(print(self_ty)); if let Some(trait_ref) = trait_ref { - p!(write(" as "), print(trait_ref)); + p!(write(" as "), print(trait_ref.print_only_trait_path())); } Ok(cx) }) @@ -468,7 +468,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("impl ")); if let Some(trait_ref) = trait_ref { - p!(print(trait_ref), write(" for ")); + p!(print(trait_ref.print_only_trait_path()), write(" for ")); } p!(print(self_ty)); @@ -619,7 +619,7 @@ pub trait PrettyPrinter<'tcx>: p!( write("{}", if first { " " } else { "+" }), - print(trait_ref)); + print(trait_ref.print_only_trait_path())); first = false; } } @@ -1696,6 +1696,30 @@ impl fmt::Display for ty::RegionKind { } } +/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only +/// the trait path. That is, it will print `Trait` instead of +/// `>`. +#[derive(Copy, Clone, TypeFoldable, Lift)] +pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); + +impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl ty::TraitRef<'tcx> { + pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> { + TraitRefPrintOnlyTraitPath(self) + } +} + +impl ty::Binder> { + pub fn print_only_trait_path(self) -> ty::Binder> { + self.map_bound(|tr| tr.print_only_trait_path()) + } +} + forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>, @@ -1705,6 +1729,7 @@ forward_display_to_print! { // because `for<'tcx>` isn't possible yet. ty::Binder<&'tcx ty::List>>, ty::Binder>, + ty::Binder>, ty::Binder>, ty::Binder>, ty::Binder>, @@ -1739,7 +1764,7 @@ define_print_and_forward_display! { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0)); let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); - p!(print(trait_ref)) + p!(print(trait_ref.print_only_trait_path())) } ty::ExistentialProjection<'tcx> { @@ -1783,7 +1808,11 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - p!(print_def_path(self.def_id, self.substs)); + p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) + } + + TraitRefPrintOnlyTraitPath<'tcx> { + p!(print_def_path(self.0.def_id, self.0.substs)); } ty::ParamTy { @@ -1799,7 +1828,8 @@ define_print_and_forward_display! { } ty::TraitPredicate<'tcx> { - p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + p!(print(self.trait_ref.self_ty()), write(": "), + print(self.trait_ref.print_only_trait_path())) } ty::ProjectionPredicate<'tcx> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index a0e66d340ae9d..ffbf8813d309d 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -223,10 +223,7 @@ impl fmt::Debug for ty::FloatVarValue { impl fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(#59188) this is used across the compiler to print - // a `TraitRef` qualified (with the Self type explicit), - // instead of having a different way to make that choice. - write!(f, "<{} as {}>", self.self_ty(), self) + fmt::Display::fmt(self, f) } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 8c4b4c16510bb..fcbc2a3301ad1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -84,7 +84,7 @@ where { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { let TraitRef { def_id, substs } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) || + self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path()) || (!self.def_id_visitor.shallow() && substs.visit_with(self)) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a33b2e32c8658..fdbf729a773aa 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1149,8 +1149,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let candidates = traits::supertraits(tcx, trait_ref).filter(|r| { self.trait_defines_associated_type_named(r.def_id(), binding.item_name) }); - self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(), - binding.item_name, binding.span) + self.one_bound_for_assoc_type( + candidates, + &trait_ref.print_only_trait_path().to_string(), + binding.item_name, + binding.span + ) }?; let (assoc_ident, def_scope) = @@ -1589,12 +1593,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(span) = bound_span { err.span_label(span, format!("ambiguous `{}` from `{}`", assoc_name, - bound)); + bound.print_only_trait_path())); } else { span_note!(&mut err, span, "associated type `{}` could derive from `{}`", ty_param_name, - bound); + bound.print_only_trait_path()); } } err.emit(); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6e37a1a47f061..f4b53b4d10604 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -502,7 +502,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !unsatisfied_predicates.is_empty() { let mut bound_list = unsatisfied_predicates.iter() - .map(|p| format!("`{} : {}`", p.self_ty(), p)) + .map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path())) .collect::>(); bound_list.sort(); bound_list.dedup(); // #35677 diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 930241262b0c1..3a4a4a50bf273 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2002,7 +2002,7 @@ fn check_impl_items_against_trait<'tcx>( "item `{}` is an associated const, \ which doesn't match its trait `{}`", ty_impl_item.ident, - impl_trait_ref); + impl_trait_ref.print_only_trait_path()); err.span_label(impl_item.span, "does not match trait"); // We can only get the spans from local trait definition // Same for E0324 and E0325 @@ -2026,7 +2026,7 @@ fn check_impl_items_against_trait<'tcx>( "item `{}` is an associated method, \ which doesn't match its trait `{}`", ty_impl_item.ident, - impl_trait_ref); + impl_trait_ref.print_only_trait_path()); err.span_label(impl_item.span, "does not match trait"); if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); @@ -2045,7 +2045,7 @@ fn check_impl_items_against_trait<'tcx>( "item `{}` is an associated type, \ which doesn't match its trait `{}`", ty_impl_item.ident, - impl_trait_ref); + impl_trait_ref.print_only_trait_path()); err.span_label(impl_item.span, "does not match trait"); if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 5bb444999681d..650e15ea8a7c8 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -35,7 +35,7 @@ impl UnsafetyChecker<'tcx> { item.span, E0199, "implementing the trait `{}` is not unsafe", - trait_ref); + trait_ref.print_only_trait_path()); } (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { @@ -43,7 +43,7 @@ impl UnsafetyChecker<'tcx> { item.span, E0200, "the trait `{}` requires an `unsafe impl` declaration", - trait_ref); + trait_ref.print_only_trait_path()); } (Unsafety::Normal, Some(attr_name), Unsafety::Normal, From 26e5fd4c964fead8c0233aa2e7170aae93435125 Mon Sep 17 00:00:00 2001 From: Mikotochan Date: Fri, 29 Nov 2019 20:47:16 +0200 Subject: [PATCH 43/43] Minor documentation fix Fixed the documentation for any as is a trait rather than a type. --- src/libcore/any.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 57a2aecd8be6d..466750fc7d2c6 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -68,7 +68,7 @@ use crate::intrinsics; // Any trait /////////////////////////////////////////////////////////////////////////////// -/// A type to emulate dynamic typing. +/// A trait to emulate dynamic typing. /// /// Most types implement `Any`. However, any type which contains a non-`'static` reference does not. /// See the [module-level documentation][mod] for more details.