diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 0cdc7c9e39ed8..20cc180f27e32 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -391,7 +391,7 @@ pub fn run_compiler( })?; None } else { - // Drop AST after creating GlobalCtxt to free memory + // Drop a reference to the AST let prof = sess.prof.clone(); let ast = queries.expansion()?.take().0; Some(Future::spawn(move || { @@ -400,6 +400,11 @@ pub fn run_compiler( })) }; + queries.global_ctxt()?; + + // Drop a reference to the AST by waiting on the lint future. + queries.lower_to_hir()?.take().1.join(); + queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; // Ensure the AST is dropped by this point. @@ -410,6 +415,7 @@ pub fn run_compiler( } if sess.opts.debugging_opts.save_analysis { + // Drop AST to free memory mem::drop(queries.expansion()?.take()); } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 4ecf45e2cc6d8..750a2e177c0a7 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -435,16 +435,16 @@ fn configure_and_expand_inner<'a>( } pub fn lower_to_hir<'res, 'tcx>( - sess: &'tcx Session, - lint_store: &LintStore, + sess: Lrc, + lint_store: Lrc, resolver: &'res mut Resolver<'_>, dep_graph: &'res DepGraph, - krate: &'res ast::Crate, + krate: Lrc, arena: &'tcx Arena<'tcx>, -) -> Result> { +) -> Result<(map::Forest<'tcx>, Future<'static, ()>)> { // Lower AST to HIR. let hir_crate = rustc_ast_lowering::lower_crate( - sess, + &sess, &dep_graph, &krate, resolver, @@ -458,23 +458,27 @@ pub fn lower_to_hir<'res, 'tcx>( let hir_forest = map::Forest::new(hir_crate, &dep_graph); - sess.time("early_lint_checks", || { - rustc_lint::check_ast_crate( - sess, - lint_store, - &krate, - false, - Some(std::mem::take(resolver.lint_buffer())), - rustc_lint::BuiltinCombinedEarlyLintPass::new(), - ) - }); + let lint_buffer = std::mem::take(resolver.lint_buffer()); // Discard hygiene data, which isn't required after lowering to HIR. if !sess.opts.debugging_opts.keep_hygiene_data { rustc_span::hygiene::clear_syntax_context_map(); } - Ok(hir_forest) + let lints = Future::spawn(move || { + sess.time("early_lint_checks", || { + rustc_lint::check_ast_crate( + &sess, + &lint_store, + &krate, + false, + Some(lint_buffer), + rustc_lint::BuiltinCombinedEarlyLintPass::new(), + ) + }) + }); + + Ok((hir_forest, lints)) } // Returns all the paths that correspond to generated files. diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index a99d487c446ab..652cb9315e838 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -77,9 +77,9 @@ pub struct Queries<'tcx> { Steal<(ast::Crate, Lrc)>, Steal>>, )>, - expansion: Query<(ast::Crate, Steal>>, Lrc)>, + expansion: Query<(Lrc, Steal>>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(&'tcx map::Forest<'tcx>, Steal)>, + lower_to_hir: Query<(&'tcx map::Forest<'tcx>, Future<'static, ()>, Steal)>, prepare_outputs: Query, global_ctxt: Query>, ongoing_codegen: Query>, @@ -163,7 +163,7 @@ impl<'tcx> Queries<'tcx> { pub fn expansion( &self, - ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { + ) -> Result<&Query<(Lrc, Steal>>, Lrc)>> { self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let (krate, lint_store) = self.register_plugins()?.peek().0.steal(); @@ -176,7 +176,7 @@ impl<'tcx> Queries<'tcx> { &crate_name, ) .map(|(krate, resolver)| { - (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store) + (Lrc::new(krate), Steal::new(Rc::new(RefCell::new(resolver))), lint_store) }) }) } @@ -204,25 +204,26 @@ impl<'tcx> Queries<'tcx> { pub fn lower_to_hir( &'tcx self, - ) -> Result<&Query<(&'tcx map::Forest<'tcx>, Steal)>> { + ) -> Result<&Query<(&'tcx map::Forest<'tcx>, Future<'static, ()>, Steal)>> + { self.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); - let krate = &peeked.0; + let krate = peeked.0.clone(); let resolver = peeked.1.steal(); - let lint_store = &peeked.2; - let hir = resolver.borrow_mut().access(|resolver| { + let lint_store = peeked.2.clone(); + let (hir, lints) = resolver.borrow_mut().access(|resolver| { passes::lower_to_hir( - self.session(), + self.session().clone(), lint_store, resolver, &*self.dep_graph()?.peek(), - &krate, + krate, &self.arena, ) })?; let hir = self.arena.alloc(hir); - Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) + Ok((hir, lints, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } @@ -248,7 +249,7 @@ impl<'tcx> Queries<'tcx> { let outputs = self.prepare_outputs()?.peek().clone(); let lint_store = self.expansion()?.peek().2.clone(); let hir = self.lower_to_hir()?.peek(); - let (ref hir_forest, ref resolver_outputs) = &*hir; + let (ref hir_forest, _, ref resolver_outputs) = &*hir; let _timer = self.session().timer("create_global_ctxt"); Ok(passes::create_global_ctxt( self.compiler, @@ -338,6 +339,12 @@ impl Compiler { }); }); + // Join the early lint check future if has started, but haven't been stolen yet. + let _join_lint_future = OnDrop(|| { + let result = queries.lower_to_hir.result.borrow_mut().take(); + result.map(|result| result.map(|result| result.1.join())); + }); + let ret = f(&queries); if self.session().opts.debugging_opts.query_stats { @@ -369,6 +376,7 @@ impl Compiler { queries.global_ctxt()?; // Drop AST after creating GlobalCtxt to free memory. + queries.lower_to_hir()?.take().1.join(); mem::drop(queries.expansion()?.take()); queries.ongoing_codegen()?;