From c5d42b164ca9a2fde7a147b193a842ffb928507e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 13 Jan 2020 05:30:42 +0100 Subject: [PATCH 01/43] Ensure all iterations in Rayon iterators run in the presence of panics --- src/librustc/hir/map/hir_id_validator.rs | 4 +- src/librustc/ty/mod.rs | 7 +- src/librustc_codegen_ssa/base.rs | 18 ++-- src/librustc_data_structures/sync.rs | 105 +++++++++++++-------- src/librustc_hir/hir.rs | 8 +- src/librustc_interface/passes.rs | 8 +- src/librustc_lint/late.rs | 4 +- src/librustc_mir/monomorphize/collector.rs | 4 +- 8 files changed, 94 insertions(+), 64 deletions(-) diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 76e42b8af2874..f347a5373c08e 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,6 +1,6 @@ use crate::hir::map::Map; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; +use rustc_data_structures::sync::{par_for_each, Lock}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc_hir::intravisit; @@ -12,7 +12,7 @@ pub fn check_crate(hir_map: &Map<'_>) { let errors = Lock::new(Vec::new()); - par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { + par_for_each(&hir_map.krate().modules, |(module_id, _)| { let local_def_id = hir_map.local_def_id(*module_id); hir_map.visit_item_likes_in_module( local_def_id, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e6acb6b74dc63..df1e91e440485 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -30,7 +30,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; +use rustc_data_structures::sync::{self, par_for_each, Lrc}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -2642,8 +2642,9 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn par_body_owners(self, f: F) { - par_iter(&self.hir().krate().body_ids) - .for_each(|&body_id| f(self.hir().body_owner_def_id(body_id))); + par_for_each(&self.hir().krate().body_ids, |&body_id| { + f(self.hir().body_owner_def_id(body_id)) + }); } pub fn provided_trait_methods(self, id: DefId) -> Vec { diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index efd560071202c..d74c1d50e782f 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -40,7 +40,7 @@ use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc_codegen_utils::{check_for_rustc_errors_attr, symbol_names_test}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::print_time_passes_entry; -use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; +use rustc_data_structures::sync::{par_map, Lock}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::Idx; @@ -631,15 +631,13 @@ pub fn codegen_crate( .collect(); // Compile the found CGUs in parallel. - par_iter(cgus) - .map(|(i, _)| { - let start_time = Instant::now(); - let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); - let mut time = total_codegen_time.lock(); - *time += start_time.elapsed(); - (i, module) - }) - .collect() + par_map(cgus, |(i, _)| { + let start_time = Instant::now(); + let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); + let mut time = total_codegen_time.lock(); + *time += start_time.elapsed(); + (i, module) + }) }) } else { FxHashMap::default() diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index fa98b4d72dda2..7f09e00738d9b 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -18,14 +18,33 @@ //! depending on the value of cfg!(parallel_compiler). use crate::owning_ref::{Erased, OwningRef}; +use std::any::Any; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; +use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; pub use std::sync::atomic::Ordering; pub use std::sync::atomic::Ordering::SeqCst; +pub fn catch( + store: &Lock>>, + f: impl FnOnce() -> R, +) -> Option { + catch_unwind(AssertUnwindSafe(f)) + .map_err(|err| { + *store.lock() = Some(err); + }) + .ok() +} + +pub fn resume(store: Lock>>) { + if let Some(panic) = store.into_inner() { + resume_unwind(panic); + } +} + cfg_if! { if #[cfg(not(parallel_compiler))] { pub auto trait Send {} @@ -42,7 +61,6 @@ cfg_if! { } use std::ops::Add; - use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe}; /// This is a single threaded variant of AtomicCell provided by crossbeam. /// Unlike `Atomic` this is intended for all `Copy` types, @@ -181,46 +199,40 @@ cfg_if! { ($($blocks:tt),*) => { // We catch panics here ensuring that all the blocks execute. // This makes behavior consistent with the parallel compiler. - let mut panic = None; + let panic = ::rustc_data_structures::sync::Lock::new(None); $( - if let Err(p) = ::std::panic::catch_unwind( - ::std::panic::AssertUnwindSafe(|| $blocks) - ) { - if panic.is_none() { - panic = Some(p); - } - } + ::rustc_data_structures::sync::catch(&panic, || $blocks); )* - if let Some(panic) = panic { - ::std::panic::resume_unwind(panic); - } + ::rustc_data_structures::sync::resume(panic); } } - pub use std::iter::Iterator as ParallelIterator; + use std::iter::{Iterator, IntoIterator, FromIterator}; - pub fn par_iter(t: T) -> T::IntoIter { - t.into_iter() - } - - pub fn par_for_each_in( + pub fn par_for_each( t: T, - for_each: - impl Fn(<::IntoIter as Iterator>::Item) + Sync + Send + mut for_each: impl FnMut(<::IntoIter as Iterator>::Item), ) { // We catch panics here ensuring that all the loop iterations execute. // This makes behavior consistent with the parallel compiler. - let mut panic = None; + let panic = Lock::new(None); t.into_iter().for_each(|i| { - if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) { - if panic.is_none() { - panic = Some(p); - } - } + catch(&panic, || for_each(i)); }); - if let Some(panic) = panic { - resume_unwind(panic); - } + resume(panic); + } + + pub fn par_map>( + t: T, + mut map: impl FnMut(<::IntoIter as Iterator>::Item) -> R, + ) -> C { + // We catch panics here ensuring that all the loop iterations execute. + let panic = Lock::new(None); + let r = t.into_iter().filter_map(|i| { + catch(&panic, || map(i)) + }).collect(); + resume(panic); + r } pub type MetadataRef = OwningRef, [u8]>; @@ -388,20 +400,39 @@ cfg_if! { pub use rayon_core::WorkerLocal; - pub use rayon::iter::ParallelIterator; - use rayon::iter::IntoParallelIterator; - - pub fn par_iter(t: T) -> T::Iter { - t.into_par_iter() - } + use rayon::iter::{ParallelIterator, FromParallelIterator, IntoParallelIterator}; - pub fn par_for_each_in( + pub fn par_for_each( t: T, for_each: impl Fn( <::Iter as ParallelIterator>::Item ) + Sync + Send ) { - t.into_par_iter().for_each(for_each) + // We catch panics here ensuring that all the loop iterations execute. + let panic = Lock::new(None); + t.into_par_iter().for_each(|i| { + catch(&panic, || for_each(i)); + }); + resume(panic); + } + + pub fn par_map< + T: IntoParallelIterator, + R: Send, + C: FromParallelIterator + >( + t: T, + map: impl Fn( + <::Iter as ParallelIterator>::Item + ) -> R + Sync + Send + ) -> C { + // We catch panics here ensuring that all the loop iterations execute. + let panic = Lock::new(None); + let r = t.into_par_iter().filter_map(|i| { + catch(&panic, || map(i)) + }).collect(); + resume(panic); + r } pub type MetadataRef = OwningRef, [u8]>; diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 550e3654d0800..fc016f579e2da 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -9,7 +9,7 @@ crate use FunctionRetTy::*; crate use UnsafeSource::*; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; +use rustc_data_structures::sync::{par_for_each, Send, Sync}; use rustc_errors::FatalError; use rustc_macros::HashStable_Generic; use rustc_session::node_id::NodeMap; @@ -669,17 +669,17 @@ impl Crate<'_> { { parallel!( { - par_for_each_in(&self.items, |(_, item)| { + par_for_each(&self.items, |(_, item)| { visitor.visit_item(item); }); }, { - par_for_each_in(&self.trait_items, |(_, trait_item)| { + par_for_each(&self.trait_items, |(_, trait_item)| { visitor.visit_trait_item(trait_item); }); }, { - par_for_each_in(&self.impl_items, |(_, impl_item)| { + par_for_each(&self.impl_items, |(_, impl_item)| { visitor.visit_impl_item(impl_item); }); } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c4444fbaa2fc7..58e9a26bc3875 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -21,7 +21,7 @@ use rustc_builtin_macros; 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::sync::{par_iter, Lrc, Once, ParallelIterator, WorkerLocal}; +use rustc_data_structures::sync::{par_for_each, Lrc, Once, WorkerLocal}; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::PResult; use rustc_expand::base::ExtCtxt; @@ -786,7 +786,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); }, { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { let local_def_id = tcx.hir().local_def_id(module); tcx.ensure().check_mod_loops(local_def_id); tcx.ensure().check_mod_attrs(local_def_id); @@ -811,7 +811,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }, { sess.time("liveness_and_intrinsic_checking", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { // this must run before MIR dump, because // "not all control paths return a value" is reported here. // @@ -879,7 +879,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }, { sess.time("privacy_checking_modules", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module)); }); }); diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index 30a3788377508..b1467da1bf5e5 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -17,7 +17,7 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc::hir::map::Map; use rustc::ty::{self, TyCtxt}; -use rustc_data_structures::sync::{join, par_iter, ParallelIterator}; +use rustc_data_structures::sync::{join, par_for_each}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit as hir_visit; @@ -481,7 +481,7 @@ pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( || { tcx.sess.time("module_lints", || { // Run per-module lints - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); }); }); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f5f00c9343561..677a7c64230cc 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -189,7 +189,7 @@ use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; +use rustc_data_structures::sync::{par_for_each, MTLock, MTRef}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; @@ -291,7 +291,7 @@ pub fn collect_crate_mono_items( let inlining_map: MTRef<'_, _> = &mut inlining_map; tcx.sess.time("monomorphization_collector_graph_walk", || { - par_iter(roots).for_each(|root| { + par_for_each(roots, |root| { let mut recursion_depths = DefIdMap::default(); collect_items_rec(tcx, root, visited, &mut recursion_depths, inlining_map); }); From 69276ba74f8c27a0fb33b4da2de9b43f2f4ffdf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 13 Jan 2020 09:57:52 +0100 Subject: [PATCH 02/43] Update tests --- src/test/ui/privacy/privacy2.stderr | 8 +++++++- src/test/ui/privacy/privacy3.stderr | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index 9f2359657bd7c..f55adc8c70110 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -12,7 +12,13 @@ LL | use bar::glob::foo; error: requires `sized` lang_item -error: aborting due to 3 previous errors +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 22c1e48b07d94..42ce456d962a1 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -6,6 +6,12 @@ LL | use bar::gpriv; error: requires `sized` lang_item -error: aborting due to 2 previous errors +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0432`. From 934abf2b06ec1e81d4a320bb138b71d007b3d233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 16 Jan 2020 10:58:52 +0100 Subject: [PATCH 03/43] Use $crate --- src/librustc_data_structures/sync.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 7f09e00738d9b..d51fd64e89113 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -199,11 +199,11 @@ cfg_if! { ($($blocks:tt),*) => { // We catch panics here ensuring that all the blocks execute. // This makes behavior consistent with the parallel compiler. - let panic = ::rustc_data_structures::sync::Lock::new(None); + let panic = $crate::sync::Lock::new(None); $( - ::rustc_data_structures::sync::catch(&panic, || $blocks); + $crate::sync::catch(&panic, || $blocks); )* - ::rustc_data_structures::sync::resume(panic); + $crate::sync::resume(panic); } } @@ -383,7 +383,7 @@ cfg_if! { parallel!(impl $fblock [$block, $($c,)*] [$($rest),*]) }; (impl $fblock:tt [$($blocks:tt,)*] []) => { - ::rustc_data_structures::sync::scope(|s| { + $crate::sync::scope(|s| { $( s.spawn(|_| $blocks); )* @@ -445,7 +445,7 @@ cfg_if! { macro_rules! rustc_erase_owner { ($v:expr) => {{ let v = $v; - ::rustc_data_structures::sync::assert_send_val(&v); + $crate::sync::assert_send_val(&v); v.erase_send_sync_owner() }} } From c621cd6a8c5277863040bb69193a67b1501de2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 2 Jan 2020 15:35:38 +0100 Subject: [PATCH 04/43] Parallelize type collecting and item-types checking --- src/librustc/hir/map/mod.rs | 38 ++++++++++++++++++++++++++++- src/librustc_hir/intravisit.rs | 7 ++++++ src/librustc_typeck/check/mod.rs | 12 ++++----- src/librustc_typeck/collect.rs | 7 +++--- src/librustc_typeck/lib.rs | 13 +++++++--- src/test/ui/span/issue-35987.rs | 3 ++- src/test/ui/span/issue-35987.stderr | 11 +++++++-- 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 46c5ee272d235..bf3a55e359890 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -8,10 +8,12 @@ use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; + +use rustc_data_structures::sync::{self, par_for_each}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; -use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; use rustc_hir::print::Nested; use rustc_hir::*; use rustc_index::vec::IndexVec; @@ -582,6 +584,40 @@ impl<'hir> Map<'hir> { } } + /// A parallel version of `visit_item_likes_in_module`. + pub fn par_visit_item_likes_in_module(&self, module: DefId, visitor: &V) + where + V: ParItemLikeVisitor<'hir> + sync::Sync, + { + let hir_id = self.as_local_hir_id(module).unwrap(); + + // Read the module so we'll be re-executed if new items + // appear immediately under in the module. If some new item appears + // in some nested item in the module, we'll be re-executed due to reads + // in the expect_* calls the loops below + self.read(hir_id); + + let module = &self.forest.krate.modules[&hir_id]; + + parallel!( + { + par_for_each(&module.items, |id| { + visitor.visit_item(self.expect_item(*id)); + }); + }, + { + par_for_each(&module.trait_items, |id| { + visitor.visit_trait_item(self.expect_trait_item(id.hir_id)); + }); + }, + { + par_for_each(&module.impl_items, |id| { + visitor.visit_impl_item(self.expect_impl_item(id.hir_id)); + }); + } + ); + } + /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. pub fn get(&self, id: HirId) -> Node<'hir> { // read recorded by `find` diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 3dbc5253a9abf..e952845b22cf3 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -70,6 +70,13 @@ pub trait IntoVisitor<'hir> { fn into_visitor(&self) -> Self::Visitor; } +impl<'hir, T: Clone + Visitor<'hir>> IntoVisitor<'hir> for T { + type Visitor = Self; + fn into_visitor(&self) -> Self::Visitor { + self.clone() + } +} + pub struct ParDeepVisitor(pub V); impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index baf9ae1ac2911..0da6035b96a07 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -121,7 +121,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath}; use rustc_index::vec::Idx; use rustc_span::hygiene::DesugaringKind; @@ -730,12 +730,12 @@ struct CheckItemTypesVisitor<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { - fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { +impl ParItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { + fn visit_item(&self, i: &'tcx hir::Item<'tcx>) { check_item_type(self.tcx, i); } - fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {} - fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {} + fn visit_trait_item(&self, _: &'tcx hir::TraitItem<'tcx>) {} + fn visit_impl_item(&self, _: &'tcx hir::ImplItem<'tcx>) {} } pub fn check_wf_new(tcx: TyCtxt<'_>) { @@ -744,7 +744,7 @@ pub fn check_wf_new(tcx: TyCtxt<'_>) { } fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) { - tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); + tcx.hir().par_visit_item_likes_in_module(module_def_id, &CheckItemTypesVisitor { tcx }); } fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index dca3289747e4c..9454a62c4ba92 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -38,7 +38,7 @@ use rustc_errors::{struct_span_err, Applicability, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{self, NestedVisitorMap, ParDeepVisitor, Visitor}; use rustc_hir::{GenericParamKind, Node, Unsafety}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -55,9 +55,9 @@ struct OnlySelfBounds(bool); // Main entry point fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) { - tcx.hir().visit_item_likes_in_module( + tcx.hir().par_visit_item_likes_in_module( module_def_id, - &mut CollectItemTypesVisitor { tcx }.as_deep_visitor(), + &ParDeepVisitor(CollectItemTypesVisitor { tcx }), ); } @@ -118,6 +118,7 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector { } } +#[derive(Clone)] struct CollectItemTypesVisitor<'tcx> { tcx: TyCtxt<'tcx>, } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index b951883ac195a..9f6edce89b88e 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -102,6 +102,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util; use rustc::util::common::ErrorReported; +use rustc_data_structures::sync::par_for_each; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -310,9 +311,13 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // FIXME(matthewjasper) We shouldn't need to do this. tcx.sess.track_errors(|| { tcx.sess.time("type_collecting", || { - for &module in tcx.hir().krate().modules.keys() { + // Run dependencies of type collecting before entering the loop + tcx.inferred_outlives_crate(LOCAL_CRATE); + + let _prof_timer = tcx.sess.timer("type_collecting_loop"); + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module)); - } + }); }); })?; @@ -341,9 +346,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { })?; tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); - } + }); }); tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); diff --git a/src/test/ui/span/issue-35987.rs b/src/test/ui/span/issue-35987.rs index 3a6e6ffe24910..7fa1a33ac84c1 100644 --- a/src/test/ui/span/issue-35987.rs +++ b/src/test/ui/span/issue-35987.rs @@ -3,10 +3,11 @@ struct Foo(T); use std::ops::Add; impl Add for Foo { -//~^ ERROR expected trait, found type parameter + //~^ ERROR expected trait, found type parameter type Output = usize; fn add(self, rhs: Self) -> Self::Output { + //~^ ERROR ambiguous associated type unimplemented!(); } } diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index 3245d8655e87d..2ab2400fc7c00 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -9,6 +9,13 @@ help: possible better candidate is found in another module, you can import it in LL | use std::ops::Add; | -error: aborting due to previous error +error[E0223]: ambiguous associated type + --> $DIR/issue-35987.rs:9:32 + | +LL | fn add(self, rhs: Self) -> Self::Output { + | ^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Trait>::Output` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0223, E0404. +For more information about an error, try `rustc --explain E0223`. From 8c07291d598f94403edf61ec0dd314d3943e702e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 2 Jan 2020 21:46:11 +0100 Subject: [PATCH 05/43] Tweak misc checking 1 --- src/librustc_interface/passes.rs | 13 ++++++++++++- .../min_const_fn/allow_const_fn_ptr_feature_gate.rs | 1 + .../allow_const_fn_ptr_feature_gate.stderr | 8 +++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 58e9a26bc3875..520dd53b69ee7 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -786,13 +786,24 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); }, { + tcx.get_lang_items(LOCAL_CRATE); + + let _timer = tcx.sess.timer("misc_module_passes"); par_for_each(&tcx.hir().krate().modules, |(&module, _)| { let local_def_id = tcx.hir().local_def_id(module); tcx.ensure().check_mod_loops(local_def_id); tcx.ensure().check_mod_attrs(local_def_id); - tcx.ensure().check_mod_unstable_api_usage(local_def_id); tcx.ensure().check_mod_const_bodies(local_def_id); }); + }, + { + tcx.stability_index(LOCAL_CRATE); + + let _timer = tcx.sess.timer("check_unstable_api_usage"); + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { + let local_def_id = tcx.hir().local_def_id(module); + tcx.ensure().check_mod_unstable_api_usage(local_def_id); + }); } ); }); diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs index 0f9d37292958a..86c3b8477ade4 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs @@ -7,5 +7,6 @@ const fn error(_: fn()) {} #[rustc_allow_const_fn_ptr] //~^ ERROR internal implementation detail const fn compiles(_: fn()) {} +//~^ ERROR rustc_promotable and rustc_allow_const_fn_ptr attributes must be paired fn main() {} diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr index 70a10d9a0c12a..4f93102f49fc6 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr @@ -7,6 +7,12 @@ LL | #[rustc_allow_const_fn_ptr] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error[E0717]: rustc_promotable and rustc_allow_const_fn_ptr attributes must be paired with either a rustc_const_unstable or a rustc_const_stable attribute + --> $DIR/allow_const_fn_ptr_feature_gate.rs:9:1 + | +LL | const fn compiles(_: fn()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. From bef0c618bdfcd8cb5d920062d2163d5bf50fa596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 01:10:04 +0100 Subject: [PATCH 06/43] Run item-types checking and item-bodies checking in parallel --- src/librustc_typeck/lib.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9f6edce89b88e..d654f116b6757 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -102,7 +102,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util; use rustc::util::common::ErrorReported; -use rustc_data_structures::sync::par_for_each; +use rustc_data_structures::sync::{join, par_for_each}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -345,14 +345,19 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { tcx.sess.time("wf_checking", || check::check_wf_new(tcx)); })?; - tcx.sess.time("item_types_checking", || { - par_for_each(&tcx.hir().krate().modules, |(&module, _)| { - tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); - }); + tcx.sess.time("item_types_and_item_bodies_checking", || { + join( + || { + tcx.sess.time("item_types_checking", || { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { + tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); + }); + }) + }, + || tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE)), + ) }); - tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); - check_unused::check_crate(tcx); check_for_entry_fn(tcx); From 337d6476913f17f8dce1b45a1eab5cc8731c2e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 01:51:30 +0100 Subject: [PATCH 07/43] Handle panics with `join` --- src/librustc_data_structures/sync.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index d51fd64e89113..3b0427e1d2869 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -175,7 +175,11 @@ cfg_if! { where A: FnOnce() -> RA, B: FnOnce() -> RB { - (oper_a(), oper_b()) + let panic = Lock::new(None); + let a = catch(&panic, oper_a); + let b = catch(&panic, oper_b); + resume(panic); + (a.unwrap(), b.unwrap()) } pub struct SerialScope; @@ -204,8 +208,8 @@ cfg_if! { $crate::sync::catch(&panic, || $blocks); )* $crate::sync::resume(panic); + } } - } use std::iter::{Iterator, IntoIterator, FromIterator}; @@ -220,7 +224,7 @@ cfg_if! { catch(&panic, || for_each(i)); }); resume(panic); - } + } pub fn par_map>( t: T, From 6b67617235b8939ae5b218e8aa2cabe505b544ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 01:52:02 +0100 Subject: [PATCH 08/43] Make typeck_item_bodies eval_always --- src/librustc/query/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index a20e011b91a75..57132949503b2 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -393,6 +393,7 @@ rustc_queries! { TypeChecking { query typeck_item_bodies(_: CrateNum) -> () { + eval_always desc { "type-checking all item bodies" } } From 6283565c58721b50852a7d58fdae181b7d9a2f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 01:55:13 +0100 Subject: [PATCH 09/43] Make coherence checking parallel --- src/librustc_typeck/coherence/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index fd685e77b418c..dd5a70cf57cdf 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -8,6 +8,7 @@ use rustc::traits; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; +use rustc_data_structures::sync::par_for_each; use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -141,9 +142,9 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { } pub fn check_coherence(tcx: TyCtxt<'_>) { - for &trait_def_id in tcx.hir().krate().trait_impls.keys() { + par_for_each(&tcx.hir().krate().trait_impls, |(&trait_def_id, _)| { tcx.ensure().coherent_trait(trait_def_id); - } + }); tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); tcx.sess.time("orphan_checking", || orphan::check(tcx)); From efe44ff18791c386acec7ee18443ecce539bf3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 03:46:38 +0100 Subject: [PATCH 10/43] Move privacy_access_levels out of misc checking 3 and run it in parallel with MIR borrow checking --- src/librustc_interface/passes.rs | 49 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 520dd53b69ee7..1d1503637fca5 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -837,9 +837,16 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { ); }); - sess.time("MIR_borrow_checking", || { - tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); - }); + parallel!( + { + tcx.ensure().privacy_access_levels(LOCAL_CRATE); + }, + { + sess.time("MIR_borrow_checking", || { + tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); + }); + } + ); sess.time("dumping_chalk_like_clauses", || { rustc_traits::lowering::dump_program_clauses(tcx); @@ -865,28 +872,20 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().privacy_access_levels(LOCAL_CRATE); - - parallel!( - { - tcx.ensure().check_private_in_public(LOCAL_CRATE); - }, - { - sess.time("death_checking", || rustc_passes::dead::check_crate(tcx)); - }, - { - sess.time("unused_lib_feature_checking", || { - rustc_passes::stability::check_unused_or_stable_features(tcx) - }); - }, - { - sess.time("lint_checking", || { - rustc_lint::check_crate(tcx, || { - rustc_lint::BuiltinCombinedLateLintPass::new() - }); - }); - } - ); + tcx.ensure().check_private_in_public(LOCAL_CRATE); + }, + { + sess.time("death_checking", || rustc_passes::dead::check_crate(tcx)); + }, + { + sess.time("unused_lib_feature_checking", || { + rustc_passes::stability::check_unused_or_stable_features(tcx) + }); + }, + { + sess.time("lint_checking", || { + rustc_lint::check_crate(tcx, || rustc_lint::BuiltinCombinedLateLintPass::new()); + }); }, { sess.time("privacy_checking_modules", || { From ff125ffc7ba2e3687dc4d52e621c0e54625d51de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 04:04:52 +0100 Subject: [PATCH 11/43] Move some other passes into a parallel block --- src/librustc_interface/passes.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 1d1503637fca5..45784b38ac270 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -845,21 +845,24 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("MIR_borrow_checking", || { tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); }); + }, + { + sess.time("dumping_chalk_like_clauses", || { + rustc_traits::lowering::dump_program_clauses(tcx); + }); + }, + { + sess.time("MIR_effect_checking", || { + for def_id in tcx.body_owners() { + mir::transform::check_unsafety::check_unsafety(tcx, def_id) + } + }); + }, + { + sess.time("layout_testing", || layout_test::test_layout(tcx)); } ); - sess.time("dumping_chalk_like_clauses", || { - rustc_traits::lowering::dump_program_clauses(tcx); - }); - - sess.time("MIR_effect_checking", || { - for def_id in tcx.body_owners() { - mir::transform::check_unsafety::check_unsafety(tcx, def_id) - } - }); - - sess.time("layout_testing", || layout_test::test_layout(tcx)); - // Avoid overwhelming user with errors if borrow checking failed. // I'm not sure how helpful this is, to be honest, but it avoids a // lot of annoying errors in the compile-fail tests (basically, From 7a6895fb47eefe14ffd6a8c52f15da5c9633ecb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 22:34:58 +0100 Subject: [PATCH 12/43] Make liveness checking more parallel --- src/librustc_interface/passes.rs | 21 ++++++++++----- src/librustc_passes/liveness.rs | 26 ++++++++++++++++--- .../ui/lint/lint-uppercase-variables.stderr | 16 ++++++------ 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 45784b38ac270..56a58084735dd 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -813,6 +813,19 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("misc_checking_2", || { parallel!( + { + sess.time("liveness_checking", || { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { + // this must run before MIR dump, because + // "not all control paths return a value" is reported here. + // + // maybe move the check to a MIR pass? + let local_def_id = tcx.hir().local_def_id(module); + + tcx.ensure().check_mod_liveness(local_def_id); + }); + }); + }, { sess.time("match_checking", || { tcx.par_body_owners(|def_id| { @@ -821,15 +834,9 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }); }, { - sess.time("liveness_and_intrinsic_checking", || { + sess.time("intrinsic_checking", || { par_for_each(&tcx.hir().krate().modules, |(&module, _)| { - // this must run before MIR dump, because - // "not all control paths return a value" is reported here. - // - // maybe move the check to a MIR pass? let local_def_id = tcx.hir().local_def_id(module); - - tcx.ensure().check_mod_liveness(local_def_id); tcx.ensure().check_mod_intrinsics(local_def_id); }); }); diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 7718139f6e924..da344712ab2f4 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -106,6 +106,7 @@ use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -182,11 +183,28 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { } } +struct LivenessVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + module_def_id: DefId, +} + +impl<'tcx> ParItemLikeVisitor<'tcx> for LivenessVisitor<'tcx> { + fn visit_item(&self, item: &'tcx hir::Item<'tcx>) { + IrMaps::new(self.tcx, self.module_def_id).visit_item(item); + } + + fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) { + IrMaps::new(self.tcx, self.module_def_id).visit_trait_item(trait_item); + } + + fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) { + IrMaps::new(self.tcx, self.module_def_id).visit_impl_item(impl_item); + } +} + fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: DefId) { - tcx.hir().visit_item_likes_in_module( - module_def_id, - &mut IrMaps::new(tcx, module_def_id).as_deep_visitor(), - ); + tcx.hir() + .par_visit_item_likes_in_module(module_def_id, &LivenessVisitor { tcx, module_def_id }); } pub fn provide(providers: &mut Providers<'_>) { diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr index b937832ac622d..3f44a64dbbc41 100644 --- a/src/test/ui/lint/lint-uppercase-variables.stderr +++ b/src/test/ui/lint/lint-uppercase-variables.stderr @@ -1,11 +1,3 @@ -warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` - --> $DIR/lint-uppercase-variables.rs:22:9 - | -LL | Foo => {} - | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` - | - = note: `#[warn(bindings_with_variant_name)]` on by default - warning: unused variable: `Foo` --> $DIR/lint-uppercase-variables.rs:22:9 | @@ -19,6 +11,14 @@ LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` +warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + | + = note: `#[warn(bindings_with_variant_name)]` on by default + error: structure field `X` should have a snake case name --> $DIR/lint-uppercase-variables.rs:10:5 | From db0bd38d6e1489fe94daae428bb519b954903345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Jan 2020 23:30:03 +0100 Subject: [PATCH 13/43] Prefetch upstream_monomorphizations --- src/librustc_mir/monomorphize/collector.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 677a7c64230cc..7bab9ffa8fc82 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -189,7 +189,7 @@ use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::{par_for_each, MTLock, MTRef}; +use rustc_data_structures::sync::{join, par_for_each, MTLock, MTRef}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; @@ -278,8 +278,16 @@ pub fn collect_crate_mono_items( ) -> (FxHashSet>, InliningMap<'_>) { let _prof_timer = tcx.prof.generic_activity("monomorphization_collector"); - let roots = - tcx.sess.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode)); + let (roots, _) = join( + || { + tcx.sess + .time("monomorphization_collector_root_collections", || collect_roots(tcx, mode)) + }, + || { + // Prefetch upstream_monomorphizations + tcx.upstream_monomorphizations(LOCAL_CRATE); + }, + ); debug!("building mono item graph, beginning at roots"); From 171b1bb59c5cb6b41532ceaf7d353a229aeeab81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 4 Jan 2020 00:16:37 +0100 Subject: [PATCH 14/43] Add a new misc checking 3 block --- src/librustc_interface/passes.rs | 54 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 56a58084735dd..0796ee4834a99 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -844,31 +844,33 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { ); }); - parallel!( - { - tcx.ensure().privacy_access_levels(LOCAL_CRATE); - }, - { - sess.time("MIR_borrow_checking", || { - tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); - }); - }, - { - sess.time("dumping_chalk_like_clauses", || { - rustc_traits::lowering::dump_program_clauses(tcx); - }); - }, - { - sess.time("MIR_effect_checking", || { - for def_id in tcx.body_owners() { - mir::transform::check_unsafety::check_unsafety(tcx, def_id) - } - }); - }, - { - sess.time("layout_testing", || layout_test::test_layout(tcx)); - } - ); + sess.time("misc_checking_3", || { + parallel!( + { + tcx.ensure().privacy_access_levels(LOCAL_CRATE); + }, + { + sess.time("MIR_borrow_checking", || { + tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); + }); + }, + { + sess.time("dumping_chalk_like_clauses", || { + rustc_traits::lowering::dump_program_clauses(tcx); + }); + }, + { + sess.time("MIR_effect_checking", || { + for def_id in tcx.body_owners() { + mir::transform::check_unsafety::check_unsafety(tcx, def_id) + } + }); + }, + { + sess.time("layout_testing", || layout_test::test_layout(tcx)); + } + ); + }); // Avoid overwhelming user with errors if borrow checking failed. // I'm not sure how helpful this is, to be honest, but it avoids a @@ -879,7 +881,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { return Err(ErrorReported); } - sess.time("misc_checking_3", || { + sess.time("misc_checking_4", || { parallel!( { tcx.ensure().check_private_in_public(LOCAL_CRATE); From 133190bd41b941917a617c2d9b1d2efa37d87fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 4 Jan 2020 02:52:21 +0100 Subject: [PATCH 15/43] Prefetch lint_levels and visible_parent_map --- src/librustc_interface/passes.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 0796ee4834a99..714174b06bcaf 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -796,6 +796,14 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { tcx.ensure().check_mod_const_bodies(local_def_id); }); }, + { + // Prefetch in case lints are emitted. + tcx.lint_levels(LOCAL_CRATE); + }, + { + // Prefetch in case something needs printing. + tcx.visible_parent_map(LOCAL_CRATE); + }, { tcx.stability_index(LOCAL_CRATE); From f68672b7358f3ff525b65b6f6f4d7db9dcdb5172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 11 Jan 2020 07:28:20 +0100 Subject: [PATCH 16/43] Fix duplicate test fallout --- .../ui-fulldeps/lint-plugin-forbid-attrs.rs | 1 + .../lint-plugin-forbid-attrs.stderr | 11 +- .../ui-fulldeps/lint-plugin-forbid-cmdline.rs | 1 + .../lint-plugin-forbid-cmdline.stderr | 10 +- src/test/ui-fulldeps/lint-tool-test.rs | 3 + src/test/ui-fulldeps/lint-tool-test.stderr | 40 ++++-- .../deduplicate-diagnostics.duplicate.stderr | 8 +- src/test/ui/deduplicate-diagnostics.rs | 1 + src/test/ui/error-codes/E0452.rs | 2 + src/test/ui/error-codes/E0452.stderr | 14 ++- src/test/ui/error-codes/E0453.rs | 1 + src/test/ui/error-codes/E0453.stderr | 11 +- src/test/ui/error-codes/E0602.stderr | 6 +- .../feature-gate-lint-reasons.rs | 1 + .../feature-gate-lint-reasons.stderr | 11 +- src/test/ui/lint/lint-forbid-attr.rs | 1 + src/test/ui/lint/lint-forbid-attr.stderr | 11 +- src/test/ui/lint/lint-forbid-cmdline.rs | 1 + src/test/ui/lint/lint-forbid-cmdline.stderr | 10 +- src/test/ui/lint/lint-malformed.rs | 2 + src/test/ui/lint/lint-malformed.stderr | 14 ++- .../ui/lint/lint-unknown-lint-cmdline.stderr | 11 +- src/test/ui/lint/outer-forbid.rs | 3 + src/test/ui/lint/outer-forbid.stderr | 41 ++++-- src/test/ui/lint/reasons-erroneous.rs | 20 +++ src/test/ui/lint/reasons-erroneous.stderr | 118 +++++++++++++----- src/test/ui/lint/reasons-forbidden.rs | 4 + src/test/ui/lint/reasons-forbidden.stderr | 19 ++- src/test/ui/tool_lints.rs | 1 + src/test/ui/tool_lints.stderr | 8 +- src/test/ui/unknown-lint-tool-name.rs | 2 + src/test/ui/unknown-lint-tool-name.stderr | 20 ++- 32 files changed, 340 insertions(+), 67 deletions(-) diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs index 35ddab95831db..353fe7205d4fe 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs +++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs @@ -12,6 +12,7 @@ fn lintme() { } //~ ERROR item is named 'lintme' //~^ ERROR allow(test_lint) overruled by outer forbid(test_lint) //~| ERROR allow(test_lint) overruled by outer forbid(test_lint) //~| ERROR allow(test_lint) overruled by outer forbid(test_lint) +//~| ERROR allow(test_lint) overruled by outer forbid(test_lint) pub fn main() { lintme(); } diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr index f93a0a0de5377..b638c0978a64e 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr +++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr @@ -45,6 +45,15 @@ LL | #![forbid(test_lint)] LL | #[allow(test_lint)] | ^^^^^^^^^ overruled by previous forbid -error: aborting due to 4 previous errors +error[E0453]: allow(test_lint) overruled by outer forbid(test_lint) + --> $DIR/lint-plugin-forbid-attrs.rs:11:9 + | +LL | #![forbid(test_lint)] + | --------- `forbid` level set here +... +LL | #[allow(test_lint)] + | ^^^^^^^^^ overruled by previous forbid + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs index 695d3aef16905..daa7eedf0f23f 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs +++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs @@ -10,6 +10,7 @@ fn lintme() { } //~ ERROR item is named 'lintme' #[allow(test_lint)] //~ ERROR allow(test_lint) overruled by outer forbid(test_lint) //~| ERROR allow(test_lint) overruled by outer forbid(test_lint) //~| ERROR allow(test_lint) overruled by outer forbid(test_lint) + //~| ERROR allow(test_lint) overruled by outer forbid(test_lint) pub fn main() { lintme(); } diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr index 0302ec84d5620..7a8dbd5976b30 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr +++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr @@ -38,6 +38,14 @@ LL | #[allow(test_lint)] | = note: `forbid` lint level was set on command line -error: aborting due to 4 previous errors +error[E0453]: allow(test_lint) overruled by outer forbid(test_lint) + --> $DIR/lint-plugin-forbid-cmdline.rs:10:9 + | +LL | #[allow(test_lint)] + | ^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui-fulldeps/lint-tool-test.rs b/src/test/ui-fulldeps/lint-tool-test.rs index f92bcd213b844..0d04eb6fcfa96 100644 --- a/src/test/ui-fulldeps/lint-tool-test.rs +++ b/src/test/ui-fulldeps/lint-tool-test.rs @@ -10,10 +10,12 @@ //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future +//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future #![deny(clippy_group)] //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future +//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future fn lintme() { } //~ ERROR item is named 'lintme' @@ -30,6 +32,7 @@ pub fn main() { //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future +//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist` fn hello() { fn lintmetoo() { } diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr index 809b9ac16205d..713548b1fd32a 100644 --- a/src/test/ui-fulldeps/lint-tool-test.stderr +++ b/src/test/ui-fulldeps/lint-tool-test.stderr @@ -7,19 +7,19 @@ LL | #![cfg_attr(foo, warn(test_lint))] = note: `#[warn(renamed_and_removed_lints)]` on by default warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore - --> $DIR/lint-tool-test.rs:29:9 + --> $DIR/lint-tool-test.rs:31:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` warning: unknown lint: `this_lint_does_not_exist` - --> $DIR/lint-tool-test.rs:33:8 + --> $DIR/lint-tool-test.rs:36:8 | LL | #[deny(this_lint_does_not_exist)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,13 +33,13 @@ LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore - --> $DIR/lint-tool-test.rs:29:9 + --> $DIR/lint-tool-test.rs:31:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` @@ -59,39 +59,57 @@ LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` error: item is named 'lintme' - --> $DIR/lint-tool-test.rs:18:1 + --> $DIR/lint-tool-test.rs:20:1 | LL | fn lintme() { } | ^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]` error: item is named 'lintmetoo' - --> $DIR/lint-tool-test.rs:26:5 + --> $DIR/lint-tool-test.rs:28:5 | LL | fn lintmetoo() { } | ^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]` warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore - --> $DIR/lint-tool-test.rs:29:9 + --> $DIR/lint-tool-test.rs:31:9 + | +LL | #[allow(test_group)] + | ^^^^^^^^^^ help: change it to: `clippy::test_group` + +warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore + --> $DIR/lint-tool-test.rs:9:23 + | +LL | #![cfg_attr(foo, warn(test_lint))] + | ^^^^^^^^^ help: change it to: `clippy::test_lint` + +warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore + --> $DIR/lint-tool-test.rs:14:9 + | +LL | #![deny(clippy_group)] + | ^^^^^^^^^^^^ help: change it to: `clippy::group` + +warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore + --> $DIR/lint-tool-test.rs:31:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` diff --git a/src/test/ui/deduplicate-diagnostics.duplicate.stderr b/src/test/ui/deduplicate-diagnostics.duplicate.stderr index 3b100b59995f0..49dd15f6a5e01 100644 --- a/src/test/ui/deduplicate-diagnostics.duplicate.stderr +++ b/src/test/ui/deduplicate-diagnostics.duplicate.stderr @@ -28,6 +28,12 @@ error[E0452]: malformed lint attribute input LL | #[deny("literal")] | ^^^^^^^^^ bad attribute argument -error: aborting due to 5 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:8:8 + | +LL | #[deny("literal")] + | ^^^^^^^^^ bad attribute argument + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/src/test/ui/deduplicate-diagnostics.rs b/src/test/ui/deduplicate-diagnostics.rs index c5d41ff2fdac3..2f72c6e61b4b7 100644 --- a/src/test/ui/deduplicate-diagnostics.rs +++ b/src/test/ui/deduplicate-diagnostics.rs @@ -8,4 +8,5 @@ struct S; #[deny("literal")] //~ ERROR malformed lint attribute input //[duplicate]~| ERROR malformed lint attribute input //[duplicate]~| ERROR malformed lint attribute input + //[duplicate]~| ERROR malformed lint attribute input fn main() {} diff --git a/src/test/ui/error-codes/E0452.rs b/src/test/ui/error-codes/E0452.rs index 4e5a6c9301467..9355f9a41a0e6 100644 --- a/src/test/ui/error-codes/E0452.rs +++ b/src/test/ui/error-codes/E0452.rs @@ -4,5 +4,7 @@ //~| ERROR E0452 //~| ERROR E0452 //~| ERROR E0452 + //~| ERROR E0452 + //~| ERROR E0452 fn main() { } diff --git a/src/test/ui/error-codes/E0452.stderr b/src/test/ui/error-codes/E0452.stderr index 30c11e3274e1c..e37602f29f765 100644 --- a/src/test/ui/error-codes/E0452.stderr +++ b/src/test/ui/error-codes/E0452.stderr @@ -34,6 +34,18 @@ error[E0452]: malformed lint attribute input LL | #![allow(foo = "")] | ^^^^^^^^ bad attribute argument -error: aborting due to 6 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/E0452.rs:1:10 + | +LL | #![allow(foo = "")] + | ^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/E0452.rs:1:10 + | +LL | #![allow(foo = "")] + | ^^^^^^^^ bad attribute argument + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/src/test/ui/error-codes/E0453.rs b/src/test/ui/error-codes/E0453.rs index 69155b0688bc0..f4bc3e049a7da 100644 --- a/src/test/ui/error-codes/E0453.rs +++ b/src/test/ui/error-codes/E0453.rs @@ -4,5 +4,6 @@ //~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case) //~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case) //~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case) +//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case) fn main() { } diff --git a/src/test/ui/error-codes/E0453.stderr b/src/test/ui/error-codes/E0453.stderr index 138e8483461c9..3ff4f4aef57a7 100644 --- a/src/test/ui/error-codes/E0453.stderr +++ b/src/test/ui/error-codes/E0453.stderr @@ -25,6 +25,15 @@ LL | LL | #[allow(non_snake_case)] | ^^^^^^^^^^^^^^ overruled by previous forbid -error: aborting due to 3 previous errors +error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case) + --> $DIR/E0453.rs:3:9 + | +LL | #![forbid(non_snake_case)] + | -------------- `forbid` level set here +LL | +LL | #[allow(non_snake_case)] + | ^^^^^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/error-codes/E0602.stderr b/src/test/ui/error-codes/E0602.stderr index 70137cb166206..32138e63a4bfb 100644 --- a/src/test/ui/error-codes/E0602.stderr +++ b/src/test/ui/error-codes/E0602.stderr @@ -10,6 +10,10 @@ error[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` -error: aborting due to 3 previous errors +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs index b124e9b2f4d71..2d15bf99613d8 100644 --- a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs +++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs @@ -2,5 +2,6 @@ //~^ ERROR lint reasons are experimental //~| ERROR lint reasons are experimental //~| ERROR lint reasons are experimental +//~| ERROR lint reasons are experimental fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr index 08ba9d0d3a313..4843f7385042e 100644 --- a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr +++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr @@ -25,6 +25,15 @@ LL | #![warn(nonstandard_style, reason = "the standard should be respected")] = note: for more information, see https://github.com/rust-lang/rust/issues/54503 = help: add `#![feature(lint_reasons)]` to the crate attributes to enable -error: aborting due to 3 previous errors +error[E0658]: lint reasons are experimental + --> $DIR/feature-gate-lint-reasons.rs:1:28 + | +LL | #![warn(nonstandard_style, reason = "the standard should be respected")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54503 + = help: add `#![feature(lint_reasons)]` to the crate attributes to enable + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/lint/lint-forbid-attr.rs b/src/test/ui/lint/lint-forbid-attr.rs index 13b28e8830b62..6d12215e99d6a 100644 --- a/src/test/ui/lint/lint-forbid-attr.rs +++ b/src/test/ui/lint/lint-forbid-attr.rs @@ -4,5 +4,6 @@ //~^ ERROR allow(deprecated) overruled by outer forbid(deprecated) //~| ERROR allow(deprecated) overruled by outer forbid(deprecated) //~| ERROR allow(deprecated) overruled by outer forbid(deprecated) +//~| ERROR allow(deprecated) overruled by outer forbid(deprecated) fn main() { } diff --git a/src/test/ui/lint/lint-forbid-attr.stderr b/src/test/ui/lint/lint-forbid-attr.stderr index bf138c317e93d..3b00a0144aa03 100644 --- a/src/test/ui/lint/lint-forbid-attr.stderr +++ b/src/test/ui/lint/lint-forbid-attr.stderr @@ -25,6 +25,15 @@ LL | LL | #[allow(deprecated)] | ^^^^^^^^^^ overruled by previous forbid -error: aborting due to 3 previous errors +error[E0453]: allow(deprecated) overruled by outer forbid(deprecated) + --> $DIR/lint-forbid-attr.rs:3:9 + | +LL | #![forbid(deprecated)] + | ---------- `forbid` level set here +LL | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/lint-forbid-cmdline.rs b/src/test/ui/lint/lint-forbid-cmdline.rs index 821470c86860a..69528c6f85135 100644 --- a/src/test/ui/lint/lint-forbid-cmdline.rs +++ b/src/test/ui/lint/lint-forbid-cmdline.rs @@ -3,5 +3,6 @@ #[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated) //~| ERROR allow(deprecated) overruled by outer forbid(deprecated) //~| ERROR allow(deprecated) overruled by outer forbid(deprecated) + //~| ERROR allow(deprecated) overruled by outer forbid(deprecated) fn main() { } diff --git a/src/test/ui/lint/lint-forbid-cmdline.stderr b/src/test/ui/lint/lint-forbid-cmdline.stderr index 89a4445d80068..1d2eda5db0780 100644 --- a/src/test/ui/lint/lint-forbid-cmdline.stderr +++ b/src/test/ui/lint/lint-forbid-cmdline.stderr @@ -22,6 +22,14 @@ LL | #[allow(deprecated)] | = note: `forbid` lint level was set on command line -error: aborting due to 3 previous errors +error[E0453]: allow(deprecated) overruled by outer forbid(deprecated) + --> $DIR/lint-forbid-cmdline.rs:3:9 + | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/lint-malformed.rs b/src/test/ui/lint/lint-malformed.rs index cf5570753d85d..57ec290cdfb34 100644 --- a/src/test/ui/lint/lint-malformed.rs +++ b/src/test/ui/lint/lint-malformed.rs @@ -5,4 +5,6 @@ //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute + //~| ERROR malformed lint attribute + //~| ERROR malformed lint attribute fn main() { } diff --git a/src/test/ui/lint/lint-malformed.stderr b/src/test/ui/lint/lint-malformed.stderr index 6dc8d4984445e..777197a4f4267 100644 --- a/src/test/ui/lint/lint-malformed.stderr +++ b/src/test/ui/lint/lint-malformed.stderr @@ -40,6 +40,18 @@ error[E0452]: malformed lint attribute input LL | #![allow(bar = "baz")] | ^^^^^^^^^^^ bad attribute argument -error: aborting due to 7 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr index 27e7ee7fc03bd..6bd98fa8f51ba 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr @@ -25,6 +25,15 @@ error[E0602]: unknown lint: `dead_cod` = help: did you mean: `dead_code` = note: requested on the command line with `-D dead_cod` -error: aborting due to 6 previous errors +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs index 2a38565f60364..c2e1f0cb4ba7a 100644 --- a/src/test/ui/lint/outer-forbid.rs +++ b/src/test/ui/lint/outer-forbid.rs @@ -9,16 +9,19 @@ #[allow(unused_variables)] //~ ERROR overruled //~| ERROR overruled //~| ERROR overruled + //~| ERROR overruled fn foo() {} #[allow(unused)] //~ ERROR overruled //~| ERROR overruled //~| ERROR overruled + //~| ERROR overruled fn bar() {} #[allow(nonstandard_style)] //~ ERROR overruled //~| ERROR overruled //~| ERROR overruled + //~| ERROR overruled fn main() { println!("hello forbidden world") } diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr index b2e638e7af978..b8c3171ab3a4e 100644 --- a/src/test/ui/lint/outer-forbid.stderr +++ b/src/test/ui/lint/outer-forbid.stderr @@ -8,7 +8,7 @@ LL | #[allow(unused_variables)] | ^^^^^^^^^^^^^^^^ overruled by previous forbid error[E0453]: allow(unused) overruled by outer forbid(unused) - --> $DIR/outer-forbid.rs:14:9 + --> $DIR/outer-forbid.rs:15:9 | LL | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here @@ -17,7 +17,7 @@ LL | #[allow(unused)] | ^^^^^^ overruled by previous forbid error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case) - --> $DIR/outer-forbid.rs:19:9 + --> $DIR/outer-forbid.rs:21:9 | LL | #![forbid(unused, non_snake_case)] | -------------- `forbid` level set here @@ -35,7 +35,7 @@ LL | #[allow(unused_variables)] | ^^^^^^^^^^^^^^^^ overruled by previous forbid error[E0453]: allow(unused) overruled by outer forbid(unused) - --> $DIR/outer-forbid.rs:14:9 + --> $DIR/outer-forbid.rs:15:9 | LL | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here @@ -44,7 +44,7 @@ LL | #[allow(unused)] | ^^^^^^ overruled by previous forbid error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case) - --> $DIR/outer-forbid.rs:19:9 + --> $DIR/outer-forbid.rs:21:9 | LL | #![forbid(unused, non_snake_case)] | -------------- `forbid` level set here @@ -62,7 +62,7 @@ LL | #[allow(unused_variables)] | ^^^^^^^^^^^^^^^^ overruled by previous forbid error[E0453]: allow(unused) overruled by outer forbid(unused) - --> $DIR/outer-forbid.rs:14:9 + --> $DIR/outer-forbid.rs:15:9 | LL | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here @@ -71,7 +71,7 @@ LL | #[allow(unused)] | ^^^^^^ overruled by previous forbid error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case) - --> $DIR/outer-forbid.rs:19:9 + --> $DIR/outer-forbid.rs:21:9 | LL | #![forbid(unused, non_snake_case)] | -------------- `forbid` level set here @@ -79,6 +79,33 @@ LL | #![forbid(unused, non_snake_case)] LL | #[allow(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ overruled by previous forbid -error: aborting due to 9 previous errors +error[E0453]: allow(unused_variables) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:9:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused) overruled by outer forbid(unused) + --> $DIR/outer-forbid.rs:15:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case) + --> $DIR/outer-forbid.rs:21:9 + | +LL | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs index 03cf0679fce94..d9cebdc406c52 100644 --- a/src/test/ui/lint/reasons-erroneous.rs +++ b/src/test/ui/lint/reasons-erroneous.rs @@ -4,6 +4,8 @@ //~^ ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason must be a string literal //~| NOTE reason must be a string literal //~| NOTE reason must be a string literal //~| NOTE reason must be a string literal @@ -11,6 +13,8 @@ //~^ ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason must be a string literal //~| NOTE reason must be a string literal //~| NOTE reason must be a string literal //~| NOTE reason must be a string literal @@ -21,6 +25,10 @@ //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument //~| NOTE bad attribute argument //~| NOTE bad attribute argument //~| NOTE bad attribute argument @@ -34,6 +42,10 @@ //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument //~| NOTE bad attribute argument //~| NOTE bad attribute argument //~| NOTE bad attribute argument @@ -47,6 +59,10 @@ //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument //~| NOTE bad attribute argument //~| NOTE bad attribute argument //~| NOTE bad attribute argument @@ -57,6 +73,8 @@ //~^ ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last @@ -64,6 +82,8 @@ //~^ ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr index a84167fed12d0..3a32c2ecfce5f 100644 --- a/src/test/ui/lint/reasons-erroneous.stderr +++ b/src/test/ui/lint/reasons-erroneous.stderr @@ -5,61 +5,61 @@ LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] | ^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:10:40 + --> $DIR/reasons-erroneous.rs:12:40 | LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:29 + --> $DIR/reasons-erroneous.rs:21:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:29 + --> $DIR/reasons-erroneous.rs:21:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:30:23 + --> $DIR/reasons-erroneous.rs:38:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:30:23 + --> $DIR/reasons-erroneous.rs:38:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:43:36 + --> $DIR/reasons-erroneous.rs:55:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:43:36 + --> $DIR/reasons-erroneous.rs:55:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:56:44 + --> $DIR/reasons-erroneous.rs:72:44 | LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:63:25 + --> $DIR/reasons-erroneous.rs:81:25 | LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last warning: unknown lint: `reason` - --> $DIR/reasons-erroneous.rs:70:39 + --> $DIR/reasons-erroneous.rs:90:39 | LL | #![warn(missing_copy_implementations, reason)] | ^^^^^^ @@ -73,55 +73,55 @@ LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] | ^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:10:40 + --> $DIR/reasons-erroneous.rs:12:40 | LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:29 + --> $DIR/reasons-erroneous.rs:21:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:29 + --> $DIR/reasons-erroneous.rs:21:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:30:23 + --> $DIR/reasons-erroneous.rs:38:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:30:23 + --> $DIR/reasons-erroneous.rs:38:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:43:36 + --> $DIR/reasons-erroneous.rs:55:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:43:36 + --> $DIR/reasons-erroneous.rs:55:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:56:44 + --> $DIR/reasons-erroneous.rs:72:44 | LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:63:25 + --> $DIR/reasons-erroneous.rs:81:25 | LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last @@ -133,59 +133,119 @@ LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] | ^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:10:40 + --> $DIR/reasons-erroneous.rs:12:40 | LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:29 + --> $DIR/reasons-erroneous.rs:21:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:29 + --> $DIR/reasons-erroneous.rs:21:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:30:23 + --> $DIR/reasons-erroneous.rs:38:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:30:23 + --> $DIR/reasons-erroneous.rs:38:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:43:36 + --> $DIR/reasons-erroneous.rs:55:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:43:36 + --> $DIR/reasons-erroneous.rs:55:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:56:44 + --> $DIR/reasons-erroneous.rs:72:44 | LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:63:25 + --> $DIR/reasons-erroneous.rs:81:25 | LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last -error: aborting due to 30 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:3:58 + | +LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] + | ^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:12:40 + | +LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:21:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:21:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:38:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:38:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:55:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:55:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:72:44 + | +LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] + | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:81:25 + | +LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error: aborting due to 40 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/src/test/ui/lint/reasons-forbidden.rs b/src/test/ui/lint/reasons-forbidden.rs index 6a71176aabb15..7a4a739565a36 100644 --- a/src/test/ui/lint/reasons-forbidden.rs +++ b/src/test/ui/lint/reasons-forbidden.rs @@ -5,6 +5,7 @@ //~^ NOTE `forbid` level set here //~| NOTE `forbid` level set here //~| NOTE `forbid` level set here + //~| NOTE `forbid` level set here reason = "our errors & omissions insurance policy doesn't cover unsafe Rust" )] @@ -17,9 +18,12 @@ fn main() { //~^ ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code) //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code) //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code) + //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code) //~| NOTE overruled by previous forbid //~| NOTE overruled by previous forbid //~| NOTE overruled by previous forbid + //~| NOTE overruled by previous forbid + //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust diff --git a/src/test/ui/lint/reasons-forbidden.stderr b/src/test/ui/lint/reasons-forbidden.stderr index 0954edea7378c..3ce1b332c369a 100644 --- a/src/test/ui/lint/reasons-forbidden.stderr +++ b/src/test/ui/lint/reasons-forbidden.stderr @@ -1,5 +1,5 @@ error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code) - --> $DIR/reasons-forbidden.rs:16:13 + --> $DIR/reasons-forbidden.rs:17:13 | LL | unsafe_code, | ----------- `forbid` level set here @@ -10,7 +10,7 @@ LL | #[allow(unsafe_code)] = note: our errors & omissions insurance policy doesn't cover unsafe Rust error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code) - --> $DIR/reasons-forbidden.rs:16:13 + --> $DIR/reasons-forbidden.rs:17:13 | LL | unsafe_code, | ----------- `forbid` level set here @@ -21,7 +21,7 @@ LL | #[allow(unsafe_code)] = note: our errors & omissions insurance policy doesn't cover unsafe Rust error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code) - --> $DIR/reasons-forbidden.rs:16:13 + --> $DIR/reasons-forbidden.rs:17:13 | LL | unsafe_code, | ----------- `forbid` level set here @@ -31,6 +31,17 @@ LL | #[allow(unsafe_code)] | = note: our errors & omissions insurance policy doesn't cover unsafe Rust -error: aborting due to 3 previous errors +error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code) + --> $DIR/reasons-forbidden.rs:17:13 + | +LL | unsafe_code, + | ----------- `forbid` level set here +... +LL | #[allow(unsafe_code)] + | ^^^^^^^^^^^ overruled by previous forbid + | + = note: our errors & omissions insurance policy doesn't cover unsafe Rust + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs index 9c8540eede792..3f79f8c7b08ab 100644 --- a/src/test/ui/tool_lints.rs +++ b/src/test/ui/tool_lints.rs @@ -2,4 +2,5 @@ //~^ ERROR an unknown tool name found in scoped lint: `foo::bar` //~| ERROR an unknown tool name found in scoped lint: `foo::bar` //~| ERROR an unknown tool name found in scoped lint: `foo::bar` +//~| ERROR an unknown tool name found in scoped lint: `foo::bar` fn main() {} diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr index 86f87784eaf86..90f15d0ad7ee0 100644 --- a/src/test/ui/tool_lints.stderr +++ b/src/test/ui/tool_lints.stderr @@ -16,5 +16,11 @@ error[E0710]: an unknown tool name found in scoped lint: `foo::bar` LL | #[warn(foo::bar)] | ^^^ -error: aborting due to 3 previous errors +error[E0710]: an unknown tool name found in scoped lint: `foo::bar` + --> $DIR/tool_lints.rs:1:8 + | +LL | #[warn(foo::bar)] + | ^^^ + +error: aborting due to 4 previous errors diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs index 182aec34b4781..fe67df6c4cc29 100644 --- a/src/test/ui/unknown-lint-tool-name.rs +++ b/src/test/ui/unknown-lint-tool-name.rs @@ -1,8 +1,10 @@ #![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar` //~| ERROR an unknown tool name found in scoped lint: `foo::bar` //~| ERROR an unknown tool name found in scoped lint: `foo::bar` + //~| ERROR an unknown tool name found in scoped lint: `foo::bar` #[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar` //~| ERROR an unknown tool name found in scoped lint: `foo::bar` //~| ERROR an unknown tool name found in scoped lint: `foo::bar` + //~| ERROR an unknown tool name found in scoped lint: `foo::bar` fn main() {} diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr index 1940f61a47b68..1f5f9b014a80f 100644 --- a/src/test/ui/unknown-lint-tool-name.stderr +++ b/src/test/ui/unknown-lint-tool-name.stderr @@ -5,7 +5,7 @@ LL | #![deny(foo::bar)] | ^^^ error[E0710]: an unknown tool name found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:5:9 + --> $DIR/unknown-lint-tool-name.rs:6:9 | LL | #[allow(foo::bar)] | ^^^ @@ -17,7 +17,7 @@ LL | #![deny(foo::bar)] | ^^^ error[E0710]: an unknown tool name found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:5:9 + --> $DIR/unknown-lint-tool-name.rs:6:9 | LL | #[allow(foo::bar)] | ^^^ @@ -29,10 +29,22 @@ LL | #![deny(foo::bar)] | ^^^ error[E0710]: an unknown tool name found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:5:9 + --> $DIR/unknown-lint-tool-name.rs:6:9 | LL | #[allow(foo::bar)] | ^^^ -error: aborting due to 6 previous errors +error[E0710]: an unknown tool name found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:1:9 + | +LL | #![deny(foo::bar)] + | ^^^ + +error[E0710]: an unknown tool name found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:6:9 + | +LL | #[allow(foo::bar)] + | ^^^ + +error: aborting due to 8 previous errors From c7aabbd288be7ccaa3578c2fd656256c827f5aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 13 Jan 2020 11:36:01 +0100 Subject: [PATCH 17/43] Drop `ensure` for privacy_access_levels. Add some comments. --- src/librustc_interface/passes.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 714174b06bcaf..253650feabc70 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -786,6 +786,8 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); }, { + // This is used by the loop below. + // Make sure it is complete before we fan out. tcx.get_lang_items(LOCAL_CRATE); let _timer = tcx.sess.timer("misc_module_passes"); @@ -805,6 +807,8 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { tcx.visible_parent_map(LOCAL_CRATE); }, { + // This is used by `check_mod_unstable_api_usage`. + // Make sure it is complete before we fan out. tcx.stability_index(LOCAL_CRATE); let _timer = tcx.sess.timer("check_unstable_api_usage"); @@ -855,7 +859,8 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().privacy_access_levels(LOCAL_CRATE); + // Prefetch this as it is used later by lint checking and privacy checking. + tcx.privacy_access_levels(LOCAL_CRATE); }, { sess.time("MIR_borrow_checking", || { From 477ad9834fdc69383866dcd15f0510667df9777f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 11 Jan 2020 12:32:00 +0100 Subject: [PATCH 18/43] Calculate accessor_map in parallel earlier --- src/librustc_mir/monomorphize/partitioning.rs | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 0def51a6a33e5..199493e3122e0 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -104,7 +104,7 @@ use rustc::ty::print::characteristic_def_id_of_type; use rustc::ty::query::Providers; use rustc::ty::{self, DefIdTree, InstanceDef, TyCtxt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync; +use rustc_data_structures::sync::{self, join}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_span::symbol::Symbol; @@ -132,17 +132,20 @@ pub fn partition<'tcx, I>( inlining_map: &InliningMap<'tcx>, ) -> Vec> where - I: Iterator>, + I: Iterator> + sync::Send, { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning"); // In the first step, we place all regular monomorphizations into their // respective 'home' codegen unit. Regular monomorphizations are all // functions and statics defined in the local crate. - let mut initial_partitioning = { - let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); - place_root_mono_items(tcx, mono_items) - }; + let (mut initial_partitioning, accessor_map) = join( + || { + let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); + place_root_mono_items(tcx, mono_items) + }, + || accessor_map(tcx, inlining_map), + ); initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); @@ -173,7 +176,7 @@ where // more freedom to optimize. if !tcx.sess.opts.cg.link_dead_code { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); - internalize_symbols(tcx, &mut post_inlining, inlining_map); + internalize_symbols(tcx, &mut post_inlining, &accessor_map); } // Finally, sort by codegen unit name, so that we get deterministic results. @@ -592,10 +595,27 @@ fn place_inlined_mono_items<'tcx>( } } +// Build a map from every monomorphization to all the monomorphizations that +// reference it. +fn accessor_map<'tcx>( + tcx: TyCtxt<'tcx>, + inlining_map: &InliningMap<'tcx>, +) -> FxHashMap, Vec>> { + let _prof_timer = tcx.prof.generic_activity("build_accessor_map"); + + let mut accessor_map: FxHashMap, Vec>> = Default::default(); + inlining_map.iter_accesses(|accessor, accessees| { + for accessee in accessees { + accessor_map.entry(*accessee).or_default().push(accessor); + } + }); + accessor_map +} + fn internalize_symbols<'tcx>( _tcx: TyCtxt<'tcx>, partitioning: &mut PostInliningPartitioning<'tcx>, - inlining_map: &InliningMap<'tcx>, + accessor_map: &FxHashMap, Vec>>, ) { if partitioning.codegen_units.len() == 1 { // Fast path for when there is only one codegen unit. In this case we @@ -610,15 +630,6 @@ fn internalize_symbols<'tcx>( return; } - // Build a map from every monomorphization to all the monomorphizations that - // reference it. - let mut accessor_map: FxHashMap, Vec>> = Default::default(); - inlining_map.iter_accesses(|accessor, accessees| { - for accessee in accessees { - accessor_map.entry(*accessee).or_default().push(accessor); - } - }); - let mono_item_placements = &partitioning.mono_item_placements; // For each internalization candidates in each codegen unit, check if it is From 85fa6a8d6025a773e5b83a8b687adfb53ace5275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 14 Jan 2020 05:39:57 +0100 Subject: [PATCH 19/43] Add par_partition --- src/librustc_data_structures/sync.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 3b0427e1d2869..e65092147d824 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -19,6 +19,7 @@ use crate::owning_ref::{Erased, OwningRef}; use std::any::Any; +use std::cmp; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::marker::PhantomData; @@ -823,3 +824,13 @@ impl DerefMut for OneThread { &mut self.inner } } + +/// Splits the slice into parts and runs `f` on them in parallel. +pub fn par_partition<'a, T: Sync, R: Send>( + slice: &'a [T], + parts: usize, + f: impl Fn(&'a [T]) -> R + Sync, +) -> Vec { + let chunks: Vec<_> = slice.chunks(cmp::max((slice.len() + parts - 1) / parts, 1)).collect(); + par_map(chunks, |chunk| f(chunk)) +} From e478795606294e5c876dfa2735e0c7d39f6d75f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 00:37:38 +0100 Subject: [PATCH 20/43] Parallelize place_root_mono_items --- src/librustc_mir/monomorphize/partitioning.rs | 96 ++++++++++++------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 199493e3122e0..09458dfcf9a7d 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -216,10 +216,7 @@ fn place_root_mono_items<'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I) -> PreInlini where I: Iterator>, { - let mut roots = FxHashSet::default(); - let mut codegen_units = FxHashMap::default(); let is_incremental_build = tcx.sess.opts.incremental.is_some(); - let mut internalization_candidates = FxHashSet::default(); // Determine if monomorphizations instantiated in this crate will be made // available to downstream crates. This depends on whether we are in @@ -227,52 +224,77 @@ where // downstream crates. let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics(); - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); - let cgu_name_cache = &mut FxHashMap::default(); + let mono_items: Vec<_> = mono_items.collect(); - for mono_item in mono_items { - match mono_item.instantiation_mode(tcx) { - InstantiationMode::GloballyShared { .. } => {} - InstantiationMode::LocalCopy => continue, - } + let _prof_timer = tcx.prof.generic_activity("place_root_mono_items_par"); - let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item); - let is_volatile = is_incremental_build && mono_item.is_generic_fn(); + let chunks = sync::par_partition(&mono_items, 2, |chunk| { + let mut roots = Vec::new(); + let mut codegen_units = FxHashMap::default(); + let mut internalization_candidates = Vec::new(); - let codegen_unit_name = match characteristic_def_id { - Some(def_id) => compute_codegen_unit_name( - tcx, - cgu_name_builder, - def_id, - is_volatile, - cgu_name_cache, - ), - None => fallback_cgu_name(cgu_name_builder), - }; + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); + let cgu_name_cache = &mut FxHashMap::default(); - let codegen_unit = codegen_units - .entry(codegen_unit_name) - .or_insert_with(|| CodegenUnit::new(codegen_unit_name)); + for &mono_item in chunk { + match mono_item.instantiation_mode(tcx) { + InstantiationMode::GloballyShared { .. } => {} + InstantiationMode::LocalCopy => continue, + } - let mut can_be_internalized = true; - let (linkage, visibility) = mono_item_linkage_and_visibility( - tcx, - &mono_item, - &mut can_be_internalized, - export_generics, - ); - if visibility == Visibility::Hidden && can_be_internalized { - internalization_candidates.insert(mono_item); + let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item); + let is_volatile = is_incremental_build && mono_item.is_generic_fn(); + + let codegen_unit_name = match characteristic_def_id { + Some(def_id) => compute_codegen_unit_name( + tcx, + cgu_name_builder, + def_id, + is_volatile, + cgu_name_cache, + ), + None => fallback_cgu_name(cgu_name_builder), + }; + + let codegen_unit = codegen_units.entry(codegen_unit_name).or_insert_with(|| Vec::new()); + + let mut can_be_internalized = true; + let (linkage, visibility) = mono_item_linkage_and_visibility( + tcx, + &mono_item, + &mut can_be_internalized, + export_generics, + ); + if visibility == Visibility::Hidden && can_be_internalized { + internalization_candidates.push(mono_item); + } + + codegen_unit.push((mono_item, (linkage, visibility))); + roots.push(mono_item); } - codegen_unit.items_mut().insert(mono_item, (linkage, visibility)); - roots.insert(mono_item); + (roots, codegen_units, internalization_candidates) + }); + + let _prof_timer = tcx.prof.generic_activity("place_root_mono_items_merge"); + + let mut roots = FxHashSet::default(); + let mut codegen_units: FxHashMap> = FxHashMap::default(); + let mut internalization_candidates = FxHashSet::default(); + + for (chunk_roots, chunk_codegen_units, chunk_internalization_candidates) in chunks { + roots.extend(chunk_roots); + internalization_candidates.extend(chunk_internalization_candidates); + for (name, items) in chunk_codegen_units { + let codegen_unit = codegen_units.entry(name).or_insert_with(|| CodegenUnit::new(name)); + codegen_unit.items_mut().extend(items); + } } // Always ensure we have at least one CGU; otherwise, if we have a // crate with just types (for example), we could wind up with no CGU. if codegen_units.is_empty() { - let codegen_unit_name = fallback_cgu_name(cgu_name_builder); + let codegen_unit_name = fallback_cgu_name(&mut CodegenUnitNameBuilder::new(tcx)); codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name)); } From 730689efe75979920aa8d7873ee258cb49433a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 02:20:04 +0100 Subject: [PATCH 21/43] Estimate CGU cost in place_root_mono_items --- src/librustc/mir/mono.rs | 14 ++- src/librustc_mir/monomorphize/partitioning.rs | 86 ++++++++++--------- 2 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index e7a4c5b592105..996d4b83132e3 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -234,7 +234,7 @@ pub struct CodegenUnit<'tcx> { /// as well as the crate name and disambiguator. name: Symbol, items: FxHashMap, (Linkage, Visibility)>, - size_estimate: Option, + size_estimate: usize, } #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)] @@ -261,7 +261,7 @@ pub enum Visibility { impl<'tcx> CodegenUnit<'tcx> { pub fn new(name: Symbol) -> CodegenUnit<'tcx> { - CodegenUnit { name: name, items: Default::default(), size_estimate: None } + CodegenUnit { name: name, items: Default::default(), size_estimate: 0 } } pub fn name(&self) -> Symbol { @@ -293,19 +293,15 @@ impl<'tcx> CodegenUnit<'tcx> { pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) { // Estimate the size of a codegen unit as (approximately) the number of MIR // statements it corresponds to. - self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum()); + self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum(); } pub fn size_estimate(&self) -> usize { - // Should only be called if `estimate_size` has previously been called. - self.size_estimate.expect("estimate_size must be called before getting a size_estimate") + self.size_estimate } pub fn modify_size_estimate(&mut self, delta: usize) { - assert!(self.size_estimate.is_some()); - if let Some(size_estimate) = self.size_estimate { - self.size_estimate = Some(size_estimate + delta); - } + self.size_estimate += delta; } pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool { diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 09458dfcf9a7d..b68692a56bac5 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -147,8 +147,6 @@ where || accessor_map(tcx, inlining_map), ); - initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); - debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter()); // If the partitioning should produce a fixed count of codegen units, merge @@ -226,54 +224,57 @@ where let mono_items: Vec<_> = mono_items.collect(); - let _prof_timer = tcx.prof.generic_activity("place_root_mono_items_par"); + let chunks = tcx.prof.generic_activity("place_root_mono_items_par").run(|| { + sync::par_partition(&mono_items, 2, |chunk| { + let mut roots = Vec::new(); + let mut codegen_units = FxHashMap::default(); + let mut internalization_candidates = Vec::new(); - let chunks = sync::par_partition(&mono_items, 2, |chunk| { - let mut roots = Vec::new(); - let mut codegen_units = FxHashMap::default(); - let mut internalization_candidates = Vec::new(); + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); + let cgu_name_cache = &mut FxHashMap::default(); - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); - let cgu_name_cache = &mut FxHashMap::default(); + for &mono_item in chunk { + match mono_item.instantiation_mode(tcx) { + InstantiationMode::GloballyShared { .. } => {} + InstantiationMode::LocalCopy => continue, + } - for &mono_item in chunk { - match mono_item.instantiation_mode(tcx) { - InstantiationMode::GloballyShared { .. } => {} - InstantiationMode::LocalCopy => continue, - } + let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item); + let is_volatile = is_incremental_build && mono_item.is_generic_fn(); + + let codegen_unit_name = match characteristic_def_id { + Some(def_id) => compute_codegen_unit_name( + tcx, + cgu_name_builder, + def_id, + is_volatile, + cgu_name_cache, + ), + None => fallback_cgu_name(cgu_name_builder), + }; - let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item); - let is_volatile = is_incremental_build && mono_item.is_generic_fn(); + let codegen_unit = + codegen_units.entry(codegen_unit_name).or_insert_with(|| (Vec::new(), 0)); - let codegen_unit_name = match characteristic_def_id { - Some(def_id) => compute_codegen_unit_name( + let mut can_be_internalized = true; + let (linkage, visibility) = mono_item_linkage_and_visibility( tcx, - cgu_name_builder, - def_id, - is_volatile, - cgu_name_cache, - ), - None => fallback_cgu_name(cgu_name_builder), - }; + &mono_item, + &mut can_be_internalized, + export_generics, + ); + if visibility == Visibility::Hidden && can_be_internalized { + internalization_candidates.push(mono_item); + } - let codegen_unit = codegen_units.entry(codegen_unit_name).or_insert_with(|| Vec::new()); - - let mut can_be_internalized = true; - let (linkage, visibility) = mono_item_linkage_and_visibility( - tcx, - &mono_item, - &mut can_be_internalized, - export_generics, - ); - if visibility == Visibility::Hidden && can_be_internalized { - internalization_candidates.push(mono_item); - } + codegen_unit.0.push((mono_item, (linkage, visibility))); + codegen_unit.1 += mono_item.size_estimate(tcx); - codegen_unit.push((mono_item, (linkage, visibility))); - roots.push(mono_item); - } + roots.push(mono_item); + } - (roots, codegen_units, internalization_candidates) + (roots, codegen_units, internalization_candidates) + }) }); let _prof_timer = tcx.prof.generic_activity("place_root_mono_items_merge"); @@ -285,8 +286,9 @@ where for (chunk_roots, chunk_codegen_units, chunk_internalization_candidates) in chunks { roots.extend(chunk_roots); internalization_candidates.extend(chunk_internalization_candidates); - for (name, items) in chunk_codegen_units { + for (name, (items, cost)) in chunk_codegen_units { let codegen_unit = codegen_units.entry(name).or_insert_with(|| CodegenUnit::new(name)); + codegen_unit.modify_size_estimate(cost); codegen_unit.items_mut().extend(items); } } From 1a37f05fd7bdfb329c21d6a457f298a79d8c919e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 03:05:55 +0100 Subject: [PATCH 22/43] Parallelize assert_symbols_are_distinct --- src/librustc_mir/monomorphize/partitioning.rs | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index b68692a56bac5..185b54c19f733 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -102,7 +102,7 @@ use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility} use rustc::mir::mono::{InstantiationMode, MonoItem}; use rustc::ty::print::characteristic_def_id_of_type; use rustc::ty::query::Providers; -use rustc::ty::{self, DefIdTree, InstanceDef, TyCtxt}; +use rustc::ty::{self, DefIdTree, InstanceDef, SymbolName, TyCtxt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, join}; use rustc_hir::def::DefKind; @@ -125,15 +125,12 @@ fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol { name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu")) } -pub fn partition<'tcx, I>( +pub fn partition<'tcx>( tcx: TyCtxt<'tcx>, - mono_items: I, + mono_items: &[MonoItem<'tcx>], strategy: PartitioningStrategy, inlining_map: &InliningMap<'tcx>, -) -> Vec> -where - I: Iterator> + sync::Send, -{ +) -> Vec> { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning"); // In the first step, we place all regular monomorphizations into their @@ -210,10 +207,10 @@ struct PostInliningPartitioning<'tcx> { internalization_candidates: FxHashSet>, } -fn place_root_mono_items<'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I) -> PreInliningPartitioning<'tcx> -where - I: Iterator>, -{ +fn place_root_mono_items<'tcx>( + tcx: TyCtxt<'tcx>, + mono_items: &[MonoItem<'tcx>], +) -> PreInliningPartitioning<'tcx> { let is_incremental_build = tcx.sess.opts.incremental.is_some(); // Determine if monomorphizations instantiated in this crate will be made @@ -222,8 +219,6 @@ where // downstream crates. let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics(); - let mono_items: Vec<_> = mono_items.collect(); - let chunks = tcx.prof.generic_activity("place_root_mono_items_par").run(|| { sync::par_partition(&mono_items, 2, |chunk| { let mut roots = Vec::new(); @@ -827,17 +822,23 @@ where } #[inline(never)] // give this a place in the profiler -fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I) -where - I: Iterator>, - 'tcx: 'a, -{ +fn assert_symbols_are_distinct<'tcx>(tcx: TyCtxt<'tcx>, mono_items: &[MonoItem<'tcx>]) { let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct"); - let mut symbols: Vec<_> = - mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect(); + let mut symbols: Vec<(&MonoItem<'tcx>, SymbolName)> = + sync::par_partition(mono_items, 2, |chunk| { + chunk + .iter() + .map(|mono_item| (mono_item, mono_item.symbol_name(tcx))) + .collect::>() + }) + .into_iter() + .flatten() + .collect(); - symbols.sort_by_key(|sym| sym.1); + tcx.prof + .generic_activity("assert_symbols_are_distinct_sort") + .run(|| symbols.sort_by_key(|sym| sym.1)); for pair in symbols.windows(2) { let sym1 = &pair[0].1; @@ -907,6 +908,8 @@ fn collect_and_partition_mono_items( tcx.sess.abort_if_errors(); + let items: Vec<_> = items.iter().copied().collect(); + let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || { sync::join( || { @@ -916,12 +919,12 @@ fn collect_and_partition_mono_items( PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) }; - partition(tcx, items.iter().cloned(), strategy, &inlining_map) + partition(tcx, &items, strategy, &inlining_map) .into_iter() .map(Arc::new) .collect::>() }, - || assert_symbols_are_distinct(tcx, items.iter()), + || assert_symbols_are_distinct(tcx, &items), ) }); From 20fd50da70753bbe37c3f0d10c823aef381563f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 05:15:59 +0100 Subject: [PATCH 23/43] Make impl WF inference more parallel --- src/librustc_typeck/impl_wf_check.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index fb87b285fa29f..6274c41c36bc9 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -12,10 +12,11 @@ use crate::constrained_generic_params as cgp; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::sync::par_for_each; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::itemlikevisit::ParItemLikeVisitor; use std::collections::hash_map::Entry::{Occupied, Vacant}; use rustc_span::Span; @@ -56,13 +57,13 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { // We will tag this as part of the WF check -- logically, it is, // but it's one that we must perform earlier than the rest of // WfCheck. - for &module in tcx.hir().krate().modules.keys() { + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id(module)); - } + }); } fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) { - tcx.hir().visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx }); + tcx.hir().par_visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx }); } pub fn provide(providers: &mut Providers<'_>) { @@ -73,8 +74,8 @@ struct ImplWfCheck<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { +impl ParItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { + fn visit_item(&self, item: &'tcx hir::Item<'tcx>) { if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.kind { let impl_def_id = self.tcx.hir().local_def_id(item.hir_id); enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_item_refs); @@ -82,9 +83,9 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { } } - fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {} + fn visit_trait_item(&self, _trait_item: &'tcx hir::TraitItem<'tcx>) {} - fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {} + fn visit_impl_item(&self, _impl_item: &'tcx hir::ImplItem<'tcx>) {} } fn enforce_impl_params_are_constrained( From 0fdcfe1509e88f9ea3ad4122ea53b3a20130ca60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 06:42:04 +0100 Subject: [PATCH 24/43] Check `Copy` impls in parallel --- src/librustc_typeck/coherence/builtin.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 8b3db15c02b4e..af90afd948947 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -12,6 +12,7 @@ use rustc::traits::{self, ObligationCause, TraitEngine}; use rustc::ty::adjustment::CoerceUnsizedInfo; use rustc::ty::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; +use rustc_data_structures::sync::par_for_each; use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; @@ -19,9 +20,16 @@ use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { + if Some(trait_def_id) == tcx.lang_items().copy_trait() { + // Checking `Copy` impls can be expensive. Do it in parallel. + let _timer = tcx.prof.generic_activity("check_implementations_of_copy"); + par_for_each(tcx.hir().trait_impls(trait_def_id), |&impl_id| { + visit_implementation_of_copy(tcx, tcx.hir().local_def_id(impl_id)); + }); + } + Checker { tcx, trait_def_id } .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop) - .check(tcx.lang_items().copy_trait(), visit_implementation_of_copy) .check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized) .check( tcx.lang_items().dispatch_from_dyn_trait(), From 98d0f7d95cf9b3df9e40ccf0d2f23e0dda7bd3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 06:50:36 +0100 Subject: [PATCH 25/43] Prefetch mir_keys --- src/librustc_interface/passes.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 253650feabc70..758298b912791 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -806,6 +806,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { // Prefetch in case something needs printing. tcx.visible_parent_map(LOCAL_CRATE); }, + { + // Prefetch mir_keys + tcx.mir_keys(LOCAL_CRATE); + }, { // This is used by `check_mod_unstable_api_usage`. // Make sure it is complete before we fan out. From 2bc0d3fb277e7098fc843d5cd7af1dc3266f06f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 12 Jan 2020 07:12:49 +0100 Subject: [PATCH 26/43] Use a parallel block for coherence checking --- src/librustc_typeck/coherence/mod.rs | 31 +++++++++++++++++++--------- src/librustc_typeck/lib.rs | 3 +++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index dd5a70cf57cdf..a91bd83160cef 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -142,16 +142,27 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { } pub fn check_coherence(tcx: TyCtxt<'_>) { - par_for_each(&tcx.hir().krate().trait_impls, |(&trait_def_id, _)| { - tcx.ensure().coherent_trait(trait_def_id); - }); - - tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); - tcx.sess.time("orphan_checking", || orphan::check(tcx)); - - // these queries are executed for side-effects (error reporting): - tcx.ensure().crate_inherent_impls(LOCAL_CRATE); - tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE); + parallel!( + { + par_for_each(&tcx.hir().krate().trait_impls, |(&trait_def_id, _)| { + tcx.ensure().coherent_trait(trait_def_id); + }); + }, + { + tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); + }, + { + tcx.sess.time("orphan_checking", || orphan::check(tcx)); + }, + { + // This query is executed for side-effects (error reporting) + tcx.ensure().crate_inherent_impls(LOCAL_CRATE); + }, + { + // This query is executed for side-effects (error reporting) + tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE); + } + ); } /// Overlap: no two impls for the same trait are implemented for the diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index d654f116b6757..eca8a41cc60c5 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -75,6 +75,9 @@ extern crate log; #[macro_use] extern crate rustc; +#[macro_use] +extern crate rustc_data_structures; + // This is used by Clippy. pub mod expr_use_visitor; From 9bfdcdecaf7bb40c7103708a9fd3d603bb399e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 13 Jan 2020 08:24:14 +0100 Subject: [PATCH 27/43] Ensure type checking each function is stealable by other threads --- src/librustc/ty/mod.rs | 4 ++-- src/librustc_data_structures/sync.rs | 30 +++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index df1e91e440485..772bfd0992008 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -30,7 +30,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{self, par_for_each, Lrc}; +use rustc_data_structures::sync::{self, balance_par_for_each, Lrc}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -2642,7 +2642,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn par_body_owners(self, f: F) { - par_for_each(&self.hir().krate().body_ids, |&body_id| { + balance_par_for_each(&self.hir().krate().body_ids, |&body_id| { f(self.hir().body_owner_def_id(body_id)) }); } diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index e65092147d824..69d03f2668e5c 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -227,6 +227,13 @@ cfg_if! { resume(panic); } + pub fn balance_par_for_each( + t: T, + for_each: impl FnMut(<::IntoIter as Iterator>::Item), + ) { + par_for_each(t, for_each) + } + pub fn par_map>( t: T, mut map: impl FnMut(<::IntoIter as Iterator>::Item) -> R, @@ -405,7 +412,9 @@ cfg_if! { pub use rayon_core::WorkerLocal; - use rayon::iter::{ParallelIterator, FromParallelIterator, IntoParallelIterator}; + use rayon::iter::{ + ParallelIterator, IndexedParallelIterator, FromParallelIterator, IntoParallelIterator + }; pub fn par_for_each( t: T, @@ -421,6 +430,25 @@ cfg_if! { resume(panic); } + /// This does the same as `par_for_each`, + /// but each loop iteration is stealable by other threads. + pub fn balance_par_for_each( + t: T, + for_each: impl Fn( + <::Iter as ParallelIterator>::Item + ) + Sync + Send + ) + where + ::Iter: IndexedParallelIterator + { + // We catch panics here ensuring that all the loop iterations execute. + let panic = Lock::new(None); + t.into_par_iter().with_max_len(1).for_each(|i| { + catch(&panic, || for_each(i)); + }); + resume(panic); + } + pub fn par_map< T: IntoParallelIterator, R: Send, From c01063247104b9cef35b932085eff96ce9f77137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 13 Jan 2020 13:09:44 +0100 Subject: [PATCH 28/43] Tune misc_checking_1 --- src/librustc_interface/passes.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 758298b912791..5f8d5c884849a 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -785,17 +785,29 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); }, + { + let _timer = tcx.sess.timer("check_const_bodies"); + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { + let local_def_id = tcx.hir().local_def_id(module); + tcx.ensure().check_mod_const_bodies(local_def_id); + }); + }, + { + let _timer = tcx.sess.timer("check_loops"); + par_for_each(&tcx.hir().krate().modules, |(&module, _)| { + let local_def_id = tcx.hir().local_def_id(module); + tcx.ensure().check_mod_loops(local_def_id); + }); + }, { // This is used by the loop below. // Make sure it is complete before we fan out. tcx.get_lang_items(LOCAL_CRATE); - let _timer = tcx.sess.timer("misc_module_passes"); + let _timer = tcx.sess.timer("check_attrs"); par_for_each(&tcx.hir().krate().modules, |(&module, _)| { let local_def_id = tcx.hir().local_def_id(module); - tcx.ensure().check_mod_loops(local_def_id); tcx.ensure().check_mod_attrs(local_def_id); - tcx.ensure().check_mod_const_bodies(local_def_id); }); }, { From 36cbf0e772e7a6d20ab977670148cd4e87c065cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 4 Jan 2020 21:42:28 +0100 Subject: [PATCH 29/43] Prefetch queries used by the metadata encoder --- src/librustc_metadata/rmeta/encoder.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 7f8791d0c34dc..0c286b3729376 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -21,7 +21,7 @@ use rustc_index::vec::Idx; use rustc::session::config::{self, CrateType}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{join, par_for_each_in, Lrc}; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; use log::{debug, trace}; @@ -1705,6 +1705,22 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { // generated regardless of trailing bytes that end up in it. pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { + join( + || encode_metadata_impl(tcx), + || { + // Prefetch some queries used by metadata encoding + tcx.dep_graph.with_ignore(|| { + par_for_each_in(tcx.mir_keys(LOCAL_CRATE), |&def_id| { + tcx.optimized_mir(def_id); + tcx.promoted_mir(def_id); + }); + }) + }, + ) + .0 +} + +fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); encoder.emit_raw_bytes(METADATA_HEADER); From d739ca914f144544b7ae84818fcc2a0f5a2581a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 11 Jan 2020 03:42:40 +0100 Subject: [PATCH 30/43] Encode exported symbols last --- src/librustc_metadata/rmeta/encoder.rs | 12 ++++++------ src/librustc_metadata/rmeta/mod.rs | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 0c286b3729376..2c20b137c37ac 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -435,12 +435,6 @@ impl<'tcx> EncodeContext<'tcx> { let impls = self.encode_impls(); let impl_bytes = self.position() - i; - // Encode exported symbols info. - i = self.position(); - let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); - let exported_symbols = self.encode_exported_symbols(&exported_symbols); - let exported_symbols_bytes = self.position() - i; - let tcx = self.tcx; // Encode the items. @@ -481,6 +475,12 @@ impl<'tcx> EncodeContext<'tcx> { let proc_macro_data = self.encode_proc_macros(); let proc_macro_data_bytes = self.position() - i; + // Encode exported symbols info. + i = self.position(); + let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); + let exported_symbols = self.encode_exported_symbols(&exported_symbols); + let exported_symbols_bytes = self.position() - i; + let attrs = tcx.hir().krate_attrs(); let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator); diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 426ea62b8cd4c..14873c7b98cdd 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -195,7 +195,6 @@ crate struct CrateRoot<'tcx> { source_map: Lazy<[rustc_span::SourceFile]>, def_path_table: Lazy, impls: Lazy<[TraitImpls]>, - exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), interpret_alloc_index: Lazy<[u32]>, per_def: LazyPerDefTables<'tcx>, @@ -203,6 +202,8 @@ crate struct CrateRoot<'tcx> { /// The DefIndex's of any proc macros delcared by this crate. proc_macro_data: Option>, + exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), + compiler_builtins: bool, needs_allocator: bool, needs_panic_runtime: bool, From 9f257bb2d0182a52202ecc88915800b704b6d004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 11 Jan 2020 04:02:22 +0100 Subject: [PATCH 31/43] Prefetch exported symbols --- src/librustc_metadata/rmeta/encoder.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 2c20b137c37ac..48a06b7d41644 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1710,10 +1710,15 @@ pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { || { // Prefetch some queries used by metadata encoding tcx.dep_graph.with_ignore(|| { - par_for_each_in(tcx.mir_keys(LOCAL_CRATE), |&def_id| { - tcx.optimized_mir(def_id); - tcx.promoted_mir(def_id); - }); + join( + || { + par_for_each_in(tcx.mir_keys(LOCAL_CRATE), |&def_id| { + tcx.optimized_mir(def_id); + tcx.promoted_mir(def_id); + }) + }, + || tcx.exported_symbols(LOCAL_CRATE), + ); }) }, ) From 8ea02062b8aad10f57da69be3101f8725b989733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 11 Jan 2020 04:47:20 +0100 Subject: [PATCH 32/43] Make the timer more verbose --- src/librustc/ty/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ef776c88a8f7c..9cd1a6ee8a057 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1329,7 +1329,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn encode_metadata(self) -> EncodedMetadata { - let _prof_timer = self.prof.generic_activity("generate_crate_metadata"); + let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata"); self.cstore.encode_metadata(self) } From 4cea70ff9478aa0a7fb867aa7dd98a083ab4b2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 13 Jan 2020 16:23:42 +0100 Subject: [PATCH 33/43] Make metadata prefetching more accurate --- src/librustc_metadata/rmeta/encoder.rs | 82 +++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 48a06b7d41644..889fafa4ff095 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -14,6 +14,7 @@ use rustc::ty::layout::VariantIdx; use rustc::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def::CtorKind; +use rustc_hir::def_id::DefIdSet; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::{AnonConst, GenericParamKind}; use rustc_index::vec::Idx; @@ -21,7 +22,7 @@ use rustc_index::vec::Idx; use rustc::session::config::{self, CrateType}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::{join, par_for_each_in, Lrc}; +use rustc_data_structures::sync::{join, Lrc}; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; use log::{debug, trace}; @@ -38,7 +39,7 @@ use syntax::expand::is_proc_macro_attr; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; struct EncodeContext<'tcx> { opaque: opaque::Encoder, @@ -1681,6 +1682,66 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { } } +/// Used to prefetch queries which will be needed later by metadata encoding. +struct PrefetchVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + mir_keys: &'tcx DefIdSet, +} + +impl<'tcx> PrefetchVisitor<'tcx> { + fn prefetch_mir(&self, def_id: DefId) { + if self.mir_keys.contains(&def_id) { + self.tcx.optimized_mir(def_id); + self.tcx.promoted_mir(def_id); + } + } +} + +impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { + fn visit_item(&self, item: &hir::Item<'_>) { + let tcx = self.tcx; + match item.kind { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => { + self.prefetch_mir(tcx.hir().local_def_id(item.hir_id)) + } + hir::ItemKind::Fn(ref sig, ..) => { + let def_id = tcx.hir().local_def_id(item.hir_id); + let generics = tcx.generics_of(def_id); + let needs_inline = generics.requires_monomorphization(tcx) + || tcx.codegen_fn_attrs(def_id).requests_inline(); + if needs_inline || sig.header.constness == hir::Constness::Const { + self.prefetch_mir(def_id) + } + } + _ => (), + } + } + + fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) { + self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id)); + } + + fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) { + let tcx = self.tcx; + match impl_item.kind { + hir::ImplItemKind::Const(..) => { + self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id)) + } + hir::ImplItemKind::Method(ref sig, _) => { + let def_id = tcx.hir().local_def_id(impl_item.hir_id); + let generics = tcx.generics_of(def_id); + let needs_inline = generics.requires_monomorphization(tcx) + || tcx.codegen_fn_attrs(def_id).requests_inline(); + let is_const_fn = sig.header.constness == hir::Constness::Const; + if needs_inline || is_const_fn { + self.prefetch_mir(def_id) + } + } + hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => (), + } + } +} + // NOTE(eddyb) The following comment was preserved for posterity, even // though it's no longer relevant as EBML (which uses nested & tagged // "documents") was replaced with a scheme that can't go out of bounds. @@ -1708,14 +1769,21 @@ pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { join( || encode_metadata_impl(tcx), || { - // Prefetch some queries used by metadata encoding + if tcx.sess.threads() == 1 { + return; + } + // Prefetch some queries used by metadata encoding. tcx.dep_graph.with_ignore(|| { join( || { - par_for_each_in(tcx.mir_keys(LOCAL_CRATE), |&def_id| { - tcx.optimized_mir(def_id); - tcx.promoted_mir(def_id); - }) + if !tcx.sess.opts.output_types.should_codegen() { + // We won't emit MIR, so don't prefetch it. + return; + } + tcx.hir().krate().par_visit_all_item_likes(&PrefetchVisitor { + tcx, + mir_keys: tcx.mir_keys(LOCAL_CRATE), + }); }, || tcx.exported_symbols(LOCAL_CRATE), ); From 667451971564f9e530231d125cb8596c98d68506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 9 Jan 2020 10:44:29 +0100 Subject: [PATCH 34/43] Run HIR indexing and loading of query results in parallel --- src/librustc_interface/passes.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 5f8d5c884849a..d30993b7127b8 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -21,7 +21,7 @@ use rustc_builtin_macros; 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::sync::{par_for_each, Lrc, Once, WorkerLocal}; +use rustc_data_structures::sync::{join, par_for_each, Lrc, Once, WorkerLocal}; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::PResult; use rustc_expand::base::ExtCtxt; @@ -721,10 +721,13 @@ pub fn create_global_ctxt<'tcx>( let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); - // Construct the HIR map. - let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs); - - let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); + let (query_result_on_disk_cache, hir_map) = join( + || rustc_incremental::load_query_result_cache(sess), + || { + // Construct the HIR map. + map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) + }, + ); let codegen_backend = compiler.codegen_backend(); let mut local_providers = ty::query::Providers::default(); From fbb9396142428a7c68bf795de6640f7fdaac1874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 14 Jan 2020 09:19:43 +0100 Subject: [PATCH 35/43] Move check_for_entry_fn and check_unused to a later stage --- src/librustc_interface/passes.rs | 3 +++ src/librustc_typeck/check_unused.rs | 2 ++ src/librustc_typeck/lib.rs | 8 ++++--- src/test/ui/bad/bad-expr-path.rs | 2 +- src/test/ui/bad/bad-expr-path.stderr | 14 ++--------- src/test/ui/bad/bad-expr-path2.rs | 2 +- src/test/ui/bad/bad-expr-path2.stderr | 13 ++--------- src/test/ui/lint/lint-unused-imports-2.rs | 23 +++++++++++++++++++ src/test/ui/lint/lint-unused-imports-2.stderr | 14 +++++++++++ src/test/ui/lint/lint-unused-imports.rs | 11 --------- src/test/ui/lint/lint-unused-imports.stderr | 20 ++++++---------- 11 files changed, 60 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/lint/lint-unused-imports-2.rs create mode 100644 src/test/ui/lint/lint-unused-imports-2.stderr diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index d30993b7127b8..ba90729a7b5bd 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -871,6 +871,9 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { tcx.ensure().check_mod_intrinsics(local_def_id); }); }); + }, + { + typeck::check_crate_late(tcx); } ); }); diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index ec098c1d89679..ec466173a5b46 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -10,6 +10,8 @@ use rustc_span::Span; use syntax::ast; pub fn check_crate(tcx: TyCtxt<'_>) { + let _timer = tcx.sess.timer("check_unused_imports"); + let mut used_trait_imports = DefIdSet::default(); for &body_id in tcx.hir().krate().bodies.keys() { let item_def_id = tcx.hir().body_owner_def_id(body_id); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index eca8a41cc60c5..7f650bf515317 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -290,6 +290,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { } fn check_for_entry_fn(tcx: TyCtxt<'_>) { + let _timer = tcx.sess.prof.generic_activity("check_entry_fn"); match tcx.entry_fn(LOCAL_CRATE) { Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id), Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), @@ -361,12 +362,13 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { ) }); - check_unused::check_crate(tcx); - check_for_entry_fn(tcx); - if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorReported) } } +pub fn check_crate_late(tcx: TyCtxt<'_>) { + join(|| check_unused::check_crate(tcx), || check_for_entry_fn(tcx)); +} + /// A quasi-deprecated helper used in rustdoc and clippy to get /// the type from a HIR node. pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { diff --git a/src/test/ui/bad/bad-expr-path.rs b/src/test/ui/bad/bad-expr-path.rs index 31fc9cf2cb575..93df6287b6bae 100644 --- a/src/test/ui/bad/bad-expr-path.rs +++ b/src/test/ui/bad/bad-expr-path.rs @@ -1,6 +1,6 @@ mod m1 {} -fn main(arguments: Vec) { //~ ERROR `main` function has wrong type +fn main(arguments: Vec) { log(debug, m1::arguments); //~^ ERROR cannot find function `log` in this scope //~| ERROR cannot find value `debug` in this scope diff --git a/src/test/ui/bad/bad-expr-path.stderr b/src/test/ui/bad/bad-expr-path.stderr index 56bb6e2be88c4..5dfa921aa061d 100644 --- a/src/test/ui/bad/bad-expr-path.stderr +++ b/src/test/ui/bad/bad-expr-path.stderr @@ -16,16 +16,6 @@ error[E0425]: cannot find value `arguments` in module `m1` LL | log(debug, m1::arguments); | ^^^^^^^^^ not found in `m1` -error[E0580]: `main` function has wrong type - --> $DIR/bad-expr-path.rs:3:1 - | -LL | fn main(arguments: Vec) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters - | - = note: expected fn pointer `fn()` - found fn pointer `fn(std::vec::Vec)` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0425, E0580. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/bad/bad-expr-path2.rs b/src/test/ui/bad/bad-expr-path2.rs index eb88edb9071ef..737d3c42934e4 100644 --- a/src/test/ui/bad/bad-expr-path2.rs +++ b/src/test/ui/bad/bad-expr-path2.rs @@ -2,7 +2,7 @@ mod m1 { pub mod arguments {} } -fn main(arguments: Vec) { //~ ERROR `main` function has wrong type +fn main(arguments: Vec) { log(debug, m1::arguments); //~^ ERROR cannot find function `log` in this scope //~| ERROR cannot find value `debug` in this scope diff --git a/src/test/ui/bad/bad-expr-path2.stderr b/src/test/ui/bad/bad-expr-path2.stderr index e217c45b267af..98bbadd268163 100644 --- a/src/test/ui/bad/bad-expr-path2.stderr +++ b/src/test/ui/bad/bad-expr-path2.stderr @@ -16,16 +16,7 @@ error[E0423]: expected value, found module `m1::arguments` LL | log(debug, m1::arguments); | ^^^^^^^^^^^^^ not a value -error[E0580]: `main` function has wrong type - --> $DIR/bad-expr-path2.rs:5:1 - | -LL | fn main(arguments: Vec) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters - | - = note: expected fn pointer `fn()` - found fn pointer `fn(std::vec::Vec)` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0423, E0425, E0580. +Some errors have detailed explanations: E0423, E0425. For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/lint/lint-unused-imports-2.rs b/src/test/ui/lint/lint-unused-imports-2.rs new file mode 100644 index 0000000000000..fcc08c3bc725c --- /dev/null +++ b/src/test/ui/lint/lint-unused-imports-2.rs @@ -0,0 +1,23 @@ +#![deny(unused_imports)] +#![allow(dead_code)] + +// Be sure that if we just bring some methods into scope that they're also +// counted as being used. +use test::B; +// But only when actually used: do not get confused by the method with the same name. +use test::B2; //~ ERROR unused import: `test::B2` + +mod test { + pub trait B { + fn b(&self) {} + } + pub trait B2 { + fn b(&self) {} + } + pub struct C; + impl B for C {} +} + +fn main() { + test::C.b(); +} diff --git a/src/test/ui/lint/lint-unused-imports-2.stderr b/src/test/ui/lint/lint-unused-imports-2.stderr new file mode 100644 index 0000000000000..e7e6888c2a278 --- /dev/null +++ b/src/test/ui/lint/lint-unused-imports-2.stderr @@ -0,0 +1,14 @@ +error: unused import: `test::B2` + --> $DIR/lint-unused-imports-2.rs:8:5 + | +LL | use test::B2; + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint-unused-imports-2.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-unused-imports.rs b/src/test/ui/lint/lint-unused-imports.rs index 4754d8880763a..73548f1da36e8 100644 --- a/src/test/ui/lint/lint-unused-imports.rs +++ b/src/test/ui/lint/lint-unused-imports.rs @@ -13,11 +13,6 @@ use std::option::Option::{Some, None}; //~^ ERROR unused imports: `None`, `Some` use test::A; //~ ERROR unused import: `test::A` -// Be sure that if we just bring some methods into scope that they're also -// counted as being used. -use test::B; -// But only when actually used: do not get confused by the method with the same name. -use test::B2; //~ ERROR unused import: `test::B2` // Make sure this import is warned about when at least one of its imported names // is unused @@ -30,11 +25,6 @@ mod test2 { mod test { pub trait A { fn a(&self) {} } - pub trait B { fn b(&self) {} } - pub trait B2 { fn b(&self) {} } - pub struct C; - impl A for C {} - impl B for C {} } mod foo { @@ -85,6 +75,5 @@ fn main() { let mut a = 3; let mut b = 4; swap(&mut a, &mut b); - test::C.b(); let _a = foo(); } diff --git a/src/test/ui/lint/lint-unused-imports.stderr b/src/test/ui/lint/lint-unused-imports.stderr index 96d71a228a5f2..b6bf823bcd4c8 100644 --- a/src/test/ui/lint/lint-unused-imports.stderr +++ b/src/test/ui/lint/lint-unused-imports.stderr @@ -23,19 +23,19 @@ LL | use test::A; | ^^^^^^^ error: unused import: `bar` - --> $DIR/lint-unused-imports.rs:24:18 + --> $DIR/lint-unused-imports.rs:19:18 | LL | use test2::{foo, bar}; | ^^^ error: unused import: `foo::Square` - --> $DIR/lint-unused-imports.rs:52:13 + --> $DIR/lint-unused-imports.rs:42:13 | LL | use foo::Square; | ^^^^^^^^^^^ error: the item `g` is imported redundantly - --> $DIR/lint-unused-imports.rs:68:9 + --> $DIR/lint-unused-imports.rs:58:9 | LL | / fn g() { LL | | use self::g; @@ -48,13 +48,13 @@ LL | | } | |_- the item `g` is already defined here error: unused import: `self::g` - --> $DIR/lint-unused-imports.rs:68:9 + --> $DIR/lint-unused-imports.rs:58:9 | LL | use self::g; | ^^^^^^^ error: the item `foo` is imported redundantly - --> $DIR/lint-unused-imports.rs:78:9 + --> $DIR/lint-unused-imports.rs:68:9 | LL | use test2::{foo, bar}; | --- the item `foo` is already imported here @@ -63,16 +63,10 @@ LL | use test2::foo; | ^^^^^^^^^^ error: unused import: `test2::foo` - --> $DIR/lint-unused-imports.rs:78:9 + --> $DIR/lint-unused-imports.rs:68:9 | LL | use test2::foo; | ^^^^^^^^^^ -error: unused import: `test::B2` - --> $DIR/lint-unused-imports.rs:20:5 - | -LL | use test::B2; - | ^^^^^^^^ - -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors From 13910d45f20fa9fd64b46744250886df24d48679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 9 Jan 2020 10:39:56 +0100 Subject: [PATCH 36/43] Add sync::spawn --- src/librustc_data_structures/sync.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 69d03f2668e5c..c6d87f2663b26 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -199,6 +199,10 @@ cfg_if! { f(&SerialScope) } + pub fn spawn(f: impl FnOnce() + 'static) { + f() + } + #[macro_export] macro_rules! parallel { ($($blocks:tt),*) => { @@ -385,7 +389,7 @@ cfg_if! { use std; use std::thread; - pub use rayon::{join, scope}; + pub use rayon::{join, scope, spawn}; /// Runs a list of blocks in parallel. The first block is executed immediately on /// the current thread. Use that for the longest running block. From 9972b3e30d5c4f6d3ca3cc2891e58b4f8ff529c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 7 Jan 2020 04:44:08 +0100 Subject: [PATCH 37/43] Add a Future type --- src/librustc_data_structures/sync.rs | 2 + src/librustc_data_structures/sync/future.rs | 69 +++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/librustc_data_structures/sync/future.rs diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index c6d87f2663b26..5a390cbc4d2b1 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -29,6 +29,8 @@ use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; pub use std::sync::atomic::Ordering; pub use std::sync::atomic::Ordering::SeqCst; +pub mod future; + pub fn catch( store: &Lock>>, f: impl FnOnce() -> R, diff --git a/src/librustc_data_structures/sync/future.rs b/src/librustc_data_structures/sync/future.rs new file mode 100644 index 0000000000000..06714ff2ccdce --- /dev/null +++ b/src/librustc_data_structures/sync/future.rs @@ -0,0 +1,69 @@ +use crate::jobserver; +use crate::sync; +use std::mem::ManuallyDrop; +use std::panic::{self, AssertUnwindSafe}; +use std::sync::Arc; +use std::sync::Condvar; +use std::sync::Mutex; +use std::thread; + +struct FutureData<'a, R> { + // ManuallyDrop is needed here to ensure the destructor of FutureData cannot refer to 'a + func: Mutex R + sync::Send + 'a>>>>, + result: Mutex>>, + waiter: Condvar, +} +pub struct Future<'a, R> { + data: Arc>, +} + +fn create<'a, R>(f: impl FnOnce() -> R + sync::Send + 'a) -> Future<'a, R> { + let data = Arc::new(FutureData { + func: Mutex::new(ManuallyDrop::new(Some(Box::new(f)))), + result: Mutex::new(None), + waiter: Condvar::new(), + }); + Future { data: data.clone() } +} + +fn run(data: &FutureData<'_, R>) { + if let Some(func) = data.func.lock().unwrap().take() { + // Execute the function if it has not yet been joined + let r = panic::catch_unwind(AssertUnwindSafe(func)); + *data.result.lock().unwrap() = Some(r); + data.waiter.notify_all(); + } +} + +impl Future<'static, R> { + pub fn spawn(f: impl FnOnce() -> R + sync::Send + 'static) -> Self { + let result = create(f); + let data = result.data.clone(); + sync::spawn(move || run(&data)); + result + } +} + +impl<'a, R: sync::Send + 'a> Future<'a, R> { + pub fn join(self) -> R { + if let Some(func) = self.data.func.lock().unwrap().take() { + // The function was not executed yet by Rayon, just run it + func() + } else { + // The function has started executing, wait for it to complete + jobserver::release_thread(); + let mut result = self + .data + .waiter + .wait_while(self.data.result.lock().unwrap(), |result| result.is_none()) + .unwrap(); + jobserver::acquire_thread(); + match result.take().unwrap() { + Ok(r) => { + return r; + } + Err(err) => panic::resume_unwind(err), + } + } + } +} From 1e02626b7e26cbe105e93eb935c5cc480c52be7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 9 Jan 2020 10:39:56 +0100 Subject: [PATCH 38/43] Drop the AST in the background --- src/librustc_driver/lib.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 019ff431bcb97..4a181d5e5f3c0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -33,6 +33,7 @@ use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::profiling::print_time_passes_entry; +use rustc_data_structures::sync::future::Future; use rustc_data_structures::sync::SeqCst; use rustc_errors::{registry::Registry, PResult}; use rustc_feature::{find_gated_cfg, UnstableFeatures}; @@ -362,7 +363,7 @@ pub fn run_compiler( return early_exit(); } - if sess.opts.debugging_opts.save_analysis { + let drop_ast_future = 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| { @@ -386,14 +387,22 @@ pub fn run_compiler( // AST will be dropped *after* the `after_analysis` callback // (needed by the RLS) })?; + None } else { // Drop AST after creating GlobalCtxt to free memory - let _timer = sess.prof.generic_activity("drop_ast"); - mem::drop(queries.expansion()?.take()); - } + let prof = sess.prof.clone(); + let ast = queries.expansion()?.take().0; + Some(Future::spawn(move || { + let _timer = prof.generic_activity("drop_ast"); + mem::drop(ast); + })) + }; queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; + // Ensure the AST is dropped by this point. + drop_ast_future.map(|future| future.join()); + if callbacks.after_analysis(compiler, queries) == Compilation::Stop { return early_exit(); } From 62b7273eb89a23a182284ee0834e25bbbaa111f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 10 Jan 2020 05:40:42 +0100 Subject: [PATCH 39/43] Run link_binary_remove_temps in the background --- src/librustc_codegen_llvm/lib.rs | 12 +++- src/librustc_codegen_ssa/back/link.rs | 58 +++++++++++-------- src/librustc_codegen_utils/codegen_backend.rs | 3 +- .../hotplug_codegen_backend/the_backend.rs | 35 +++++------ 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index a6168128c4d44..88e8a84308903 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -44,6 +44,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_data_structures::sync::Lrc; mod back { pub mod archive; @@ -271,7 +272,7 @@ impl CodegenBackend for LlvmCodegenBackend { fn join_codegen_and_link( &self, ongoing_codegen: Box, - sess: &Session, + sess: &Lrc, dep_graph: &DepGraph, outputs: &OutputFilenames, ) -> Result<(), ErrorReported> { @@ -298,9 +299,11 @@ impl CodegenBackend for LlvmCodegenBackend { return Ok(()); } + let codegen_results = Lrc::new(codegen_results); + // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - sess.time("link_crate", || { + let cleanup_future = sess.time("link_crate", || { use crate::back::archive::LlvmArchiveBuilder; use rustc_codegen_ssa::back::link::link_binary; @@ -311,13 +314,16 @@ impl CodegenBackend for LlvmCodegenBackend { outputs, &codegen_results.crate_name.as_str(), target_cpu, - ); + ) }); // Now that we won't touch anything in the incremental compilation directory // any more, we can finalize it (which involves renaming it) rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash); + // Join the cleanup future so it drops the `Lrc` it holds. + cleanup_future.join(); + Ok(()) } } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 53ee5996432ce..0dd307a3b0024 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -8,6 +8,8 @@ use rustc::session::search_paths::PathKind; /// need out of the shared crate context before we get rid of it. use rustc::session::{filesearch, Session}; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::future::Future; +use rustc_data_structures::sync::Lrc; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; use rustc_span::symbol::Symbol; @@ -47,12 +49,12 @@ pub fn remove(sess: &Session, path: &Path) { /// Performs the linkage portion of the compilation phase. This will generate all /// of the requested outputs for this compilation session. pub fn link_binary<'a, B: ArchiveBuilder<'a>>( - sess: &'a Session, - codegen_results: &CodegenResults, + sess: &'a Lrc, + codegen_results: &Lrc, outputs: &OutputFilenames, crate_name: &str, target_cpu: &str, -) { +) -> Future<'static, ()> { let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); for &crate_type in sess.crate_types.borrow().iter() { @@ -122,34 +124,40 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( } // Remove the temporary object file and metadata if we aren't saving temps - sess.time("link_binary_remove_temps", || { - if !sess.opts.cg.save_temps { - if sess.opts.output_types.should_codegen() - && !preserve_objects_for_their_debuginfo(sess) - { - for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { - remove(sess, obj); + let sess = sess.clone(); + let codegen_results = codegen_results.clone(); + Future::spawn(move || { + let sess = &*sess; + sess.time("link_binary_remove_temps", || { + if !sess.opts.cg.save_temps { + if sess.opts.output_types.should_codegen() + && !preserve_objects_for_their_debuginfo(sess) + { + for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { + remove(sess, obj); + } } - } - for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) - { - remove(sess, obj); - } - if let Some(ref metadata_module) = codegen_results.metadata_module { - if let Some(ref obj) = metadata_module.object { + for obj in + codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) + { remove(sess, obj); } - } - if let Some(ref allocator_module) = codegen_results.allocator_module { - if let Some(ref obj) = allocator_module.object { - remove(sess, obj); + if let Some(ref metadata_module) = codegen_results.metadata_module { + if let Some(ref obj) = metadata_module.object { + remove(sess, obj); + } } - if let Some(ref bc) = allocator_module.bytecode_compressed { - remove(sess, bc); + if let Some(ref allocator_module) = codegen_results.allocator_module { + if let Some(ref obj) = allocator_module.object { + remove(sess, obj); + } + if let Some(ref bc) = allocator_module.bytecode_compressed { + remove(sess, bc); + } } } - } - }); + }); + }) } // The third parameter is for env vars, used on windows to set up the diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index fecb3986e7e08..ae506f47bf260 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -15,6 +15,7 @@ use rustc::session::Session; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; +use rustc_data_structures::sync::Lrc; use rustc_span::symbol::Symbol; pub use rustc_data_structures::sync::MetadataRef; @@ -46,7 +47,7 @@ pub trait CodegenBackend { fn join_codegen_and_link( &self, ongoing_codegen: Box, - sess: &Session, + sess: &Lrc, dep_graph: &DepGraph, outputs: &OutputFilenames, ) -> Result<(), ErrorReported>; diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 84bcd220ae766..7657f2800a78a 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -4,32 +4,33 @@ extern crate rustc; extern crate rustc_codegen_utils; #[macro_use] extern crate rustc_data_structures; -extern crate rustc_hir; -extern crate rustc_target; extern crate rustc_driver; +extern crate rustc_hir; extern crate rustc_span; +extern crate rustc_target; -use std::any::Any; -use std::sync::Arc; -use std::path::Path; -use rustc_span::symbol::Symbol; -use rustc::session::Session; +use rustc::dep_graph::DepGraph; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; use rustc::session::config::OutputFilenames; -use rustc::ty::TyCtxt; +use rustc::session::Session; use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; -use rustc::dep_graph::DepGraph; +use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_data_structures::sync::MetadataRef; use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::sync::{Lrc, MetadataRef}; +use rustc_span::symbol::Symbol; use rustc_target::spec::Target; +use std::any::Any; +use std::path::Path; +use std::sync::Arc; pub struct NoLlvmMetadataLoader; impl MetadataLoader for NoLlvmMetadataLoader { fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result { - let buf = std::fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?; + let buf = + std::fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?; let buf: OwningRef, [u8]> = OwningRef::new(buf); Ok(rustc_erase_owner!(buf.map_owner_box())) } @@ -74,21 +75,21 @@ impl CodegenBackend for TheBackend { fn join_codegen_and_link( &self, ongoing_codegen: Box, - sess: &Session, + sess: &Lrc, _dep_graph: &DepGraph, outputs: &OutputFilenames, ) -> Result<(), ErrorReported> { - use std::io::Write; use rustc::session::config::CrateType; use rustc_codegen_utils::link::out_filename; - let crate_name = ongoing_codegen.downcast::() + use std::io::Write; + let crate_name = ongoing_codegen + .downcast::() .expect("in join_codegen_and_link: ongoing_codegen is not a Symbol"); for &crate_type in sess.opts.crate_types.iter() { if crate_type != CrateType::Rlib { sess.fatal(&format!("Crate type is {:?}", crate_type)); } - let output_name = - out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); + let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); let mut out_file = ::std::fs::File::create(output_name).unwrap(); write!(out_file, "This has been \"compiled\" successfully.").unwrap(); } From 64f2bbd821afe41848984c12e831213a32d92df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 10 Jan 2020 07:50:12 +0100 Subject: [PATCH 40/43] Make copy_cgu_workproducts_to_incr_comp_cache_dir parallel --- src/librustc_codegen_ssa/back/write.rs | 61 +++++++++++------- src/librustc_incremental/persist/fs.rs | 2 +- .../persist/work_product.rs | 7 ++- src/librustc_session/session.rs | 63 ++++++++----------- 4 files changed, 69 insertions(+), 64 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 801bfdea70d6c..3356ddc7b90f3 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -21,7 +21,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{par_partition, Lrc}; use rustc_errors::emitter::Emitter; use rustc_errors::{DiagnosticId, FatalError, Handler, Level}; use rustc_fs_util::link_or_copy; @@ -239,7 +239,7 @@ pub struct CodegenContext { pub worker: usize, // The incremental compilation session directory, or None if we are not // compiling incrementally - pub incr_comp_session_dir: Option, + pub incr_comp_session_dir: Option>, // Used to update CGU re-use information during the thinlto phase. pub cgu_reuse_tracker: CguReuseTracker, // Channel back to the main control thread to send messages to @@ -473,32 +473,47 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, compiled_modules: &CompiledModules, ) -> FxHashMap { - let mut work_products = FxHashMap::default(); - if sess.opts.incremental.is_none() { - return work_products; + return FxHashMap::default(); } - let _timer = sess.timer("incr_comp_copy_cgu_workproducts"); + let _timer = sess.timer("incr_comp_copy_all_cgu_workproducts"); - for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { - let mut files = vec![]; + let session_dir = sess.incr_comp_session_dir(); - if let Some(ref path) = module.object { - files.push((WorkProductFileKind::Object, path.clone())); - } - if let Some(ref path) = module.bytecode { - files.push((WorkProductFileKind::Bytecode, path.clone())); - } - if let Some(ref path) = module.bytecode_compressed { - files.push((WorkProductFileKind::BytecodeCompressed, path.clone())); - } + // Split the modules into 3 parts, which limits usage to 3 threads. + // That seems to be all Windows' file system can handle. + let work_product_chunks = par_partition(&compiled_modules.modules, 3, |chunk| { + chunk + .iter() + .filter(|m| m.kind == ModuleKind::Regular) + .filter_map(|module| { + let mut files = vec![]; - if let Some((id, product)) = - copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) - { - work_products.insert(id, product); - } + if let Some(ref path) = module.object { + files.push((WorkProductFileKind::Object, path.clone())); + } + if let Some(ref path) = module.bytecode { + files.push((WorkProductFileKind::Bytecode, path.clone())); + } + if let Some(ref path) = module.bytecode_compressed { + files.push((WorkProductFileKind::BytecodeCompressed, path.clone())); + } + + copy_cgu_workproducts_to_incr_comp_cache_dir( + sess, + &session_dir, + &module.name, + &files, + ) + }) + .collect::>() + }); + + let mut work_products = FxHashMap::default(); + + for (id, product) in work_product_chunks.into_iter().flat_map(|chunk| chunk.into_iter()) { + work_products.insert(id, product); } work_products @@ -1029,7 +1044,7 @@ fn start_executing_work( exported_symbols, remark: sess.opts.cg.remark.clone(), worker: 0, - incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()), + incr_comp_session_dir: sess.incr_comp_session_dir_opt(), cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(), coordinator_send, diag_emitter: shared_emitter.clone(), diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index ba20006d73ccc..3b9d290f8e572 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -310,7 +310,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { let _timer = sess.timer("incr_comp_finalize_session_directory"); - let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone(); + let incr_comp_session_dir = sess.incr_comp_session_dir(); if sess.has_errors_or_delayed_span_bugs() { // If there have been any errors during compilation, we don't want to diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 65a742a202ddd..448602c42d535 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -5,10 +5,11 @@ use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; use rustc::session::Session; use rustc_fs_util::link_or_copy; use std::fs as std_fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, + session_dir: &Path, cgu_name: &str, files: &[(WorkProductFileKind, PathBuf)], ) -> Option<(WorkProductId, WorkProduct)> { @@ -17,6 +18,8 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( return None; } + let _timer = sess.prof.generic_activity("incr_comp_copy_cgu_workproducts"); + let saved_files = files .iter() .map(|&(kind, ref path)| { @@ -26,7 +29,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( WorkProductFileKind::BytecodeCompressed => "bc.z", }; let file_name = format!("{}.{}", cgu_name, extension); - let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); + let path_in_incr_dir = session_dir.join(&file_name); match link_or_copy(path, &path_in_incr_dir) { Ok(_) => Some((kind, file_name)), Err(err) => { diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index d979247b46d3a..29cbe77588d58 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -34,7 +34,7 @@ use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; use std; -use std::cell::{self, RefCell}; +use std::cell::RefCell; use std::env; use std::fmt; use std::io::Write; @@ -94,7 +94,7 @@ pub struct Session { /// macro name and definition span in the source crate. pub imported_macro_spans: OneThread>>, - incr_comp_session: OneThread>, + incr_comp_session: Lock, /// Used for incremental compilation tests. Will only be populated if /// `-Zquery-dep-graph` is specified. pub cgu_reuse_tracker: CguReuseTracker, @@ -599,41 +599,28 @@ impl Session { ) } - pub fn set_incr_session_load_dep_graph(&self, load: bool) { - let mut incr_comp_session = self.incr_comp_session.borrow_mut(); - - if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session { - *load_dep_graph = load; - } - } - - pub fn incr_session_load_dep_graph(&self) -> bool { - let incr_comp_session = self.incr_comp_session.borrow(); - match *incr_comp_session { - IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph, - _ => false, - } - } - pub fn init_incr_comp_session( &self, session_dir: PathBuf, lock_file: flock::Lock, load_dep_graph: bool, ) { - let mut incr_comp_session = self.incr_comp_session.borrow_mut(); + let mut incr_comp_session = self.incr_comp_session.lock(); if let IncrCompSession::NotInitialized = *incr_comp_session { } else { panic!("Trying to initialize IncrCompSession `{:?}`", *incr_comp_session) } - *incr_comp_session = - IncrCompSession::Active { session_directory: session_dir, lock_file, load_dep_graph }; + *incr_comp_session = IncrCompSession::Active { + session_directory: Arc::new(session_dir), + lock_file, + load_dep_graph, + }; } pub fn finalize_incr_comp_session(&self, new_directory_path: PathBuf) { - let mut incr_comp_session = self.incr_comp_session.borrow_mut(); + let mut incr_comp_session = self.incr_comp_session.lock(); if let IncrCompSession::Active { .. } = *incr_comp_session { } else { @@ -641,11 +628,12 @@ impl Session { } // Note: this will also drop the lock file, thus unlocking the directory. - *incr_comp_session = IncrCompSession::Finalized { session_directory: new_directory_path }; + *incr_comp_session = + IncrCompSession::Finalized { session_directory: Arc::new(new_directory_path) }; } pub fn mark_incr_comp_session_as_invalid(&self) { - let mut incr_comp_session = self.incr_comp_session.borrow_mut(); + let mut incr_comp_session = self.incr_comp_session.lock(); let session_directory = match *incr_comp_session { IncrCompSession::Active { ref session_directory, .. } => session_directory.clone(), @@ -657,22 +645,21 @@ impl Session { *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory }; } - pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> { - let incr_comp_session = self.incr_comp_session.borrow(); - cell::Ref::map(incr_comp_session, |incr_comp_session| match *incr_comp_session { - IncrCompSession::NotInitialized => panic!( - "trying to get session directory from `IncrCompSession`: {:?}", - *incr_comp_session, - ), + pub fn incr_comp_session_dir(&self) -> Arc { + let session = self.incr_comp_session.lock(); + match *session { + IncrCompSession::NotInitialized => { + panic!("trying to get session directory from `IncrCompSession`: {:?}", *session) + } IncrCompSession::Active { ref session_directory, .. } | IncrCompSession::Finalized { ref session_directory } | IncrCompSession::InvalidBecauseOfErrors { ref session_directory } => { - session_directory + session_directory.clone() } - }) + } } - pub fn incr_comp_session_dir_opt(&self) -> Option> { + pub fn incr_comp_session_dir_opt(&self) -> Option> { self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir()) } @@ -1050,7 +1037,7 @@ fn build_session_( recursion_limit: Once::new(), type_length_limit: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), - incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), + incr_comp_session: Lock::new(IncrCompSession::NotInitialized), cgu_reuse_tracker, prof, perf_stats: PerfStats { @@ -1188,14 +1175,14 @@ pub enum IncrCompSession { NotInitialized, /// This is the state during which the session directory is private and can /// be modified. - Active { session_directory: PathBuf, lock_file: flock::Lock, load_dep_graph: bool }, + Active { session_directory: Arc, lock_file: flock::Lock, load_dep_graph: bool }, /// This is the state after the session directory has been finalized. In this /// state, the contents of the directory must not be modified any more. - Finalized { session_directory: PathBuf }, + Finalized { session_directory: Arc }, /// This is an error state that is reached when some compilation error has /// occurred. It indicates that the contents of the session directory must /// not be used, since they might be invalid. - InvalidBecauseOfErrors { session_directory: PathBuf }, + InvalidBecauseOfErrors { session_directory: Arc }, } pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { From 0a36b4da0f16b9cff36c88b60b91769d8276a96e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 11 Jan 2020 02:13:48 +0100 Subject: [PATCH 41/43] Do incremental setup in the background --- src/librustc/ty/steal.rs | 4 +++ src/librustc_driver/lib.rs | 6 ++-- src/librustc_interface/passes.rs | 44 +++++++++++++++--------- src/librustc_interface/queries.rs | 56 ++++++++++++++++--------------- 4 files changed, 66 insertions(+), 44 deletions(-) diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs index 224e76845d708..b9948877f473f 100644 --- a/src/librustc/ty/steal.rs +++ b/src/librustc/ty/steal.rs @@ -41,4 +41,8 @@ impl Steal { let value = value_ref.take(); value.expect("attempt to read from stolen value") } + + pub fn into_inner(self) -> Option { + self.value.into_inner() + } } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4a181d5e5f3c0..0cdc7c9e39ed8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -335,11 +335,13 @@ pub fn run_compiler( } { - let (_, lint_store) = &*queries.register_plugins()?.peek(); + let peek = queries.register_plugins()?.peek(); + let peek = peek.0.borrow(); + let lint_store = &peek.1; // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { - describe_lints(&sess, &lint_store, true); + describe_lints(&sess, lint_store, true); return early_exit(); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index ba90729a7b5bd..4ecf45e2cc6d8 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -21,12 +21,14 @@ use rustc_builtin_macros; 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::sync::future::Future; use rustc_data_structures::sync::{join, par_for_each, Lrc, Once, WorkerLocal}; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::PResult; use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental; +use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; use rustc_mir as mir; use rustc_mir_build as mir_build; @@ -150,12 +152,12 @@ impl BoxedResolver { } pub fn register_plugins<'a>( - sess: &'a Session, + sess: &'a Lrc, metadata_loader: &'a dyn MetadataLoader, register_lints: impl Fn(&Session, &mut LintStore), mut krate: ast::Crate, - crate_name: &str, -) -> Result<(ast::Crate, Lrc)> { + crate_name: String, +) -> (ast::Crate, Lrc, Future<'static, Option>) { krate = sess.time("attributes_injection", || { rustc_builtin_macros::cmdline_attrs::inject( krate, @@ -178,19 +180,31 @@ pub fn register_plugins<'a>( let disambiguator = util::compute_crate_disambiguator(sess); sess.crate_disambiguator.set(disambiguator); - rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator); - if sess.opts.incremental.is_some() { - sess.time("incr_comp_garbage_collect_session_directories", || { - if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) { - warn!( - "Error while trying to garbage collect incremental \ + let sess_ = sess.clone(); + let dep_graph_future = Future::spawn(move || { + let sess = &*sess_; + rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator); + + if sess.opts.incremental.is_some() { + sess.time("incr_comp_garbage_collect_session_directories", || { + if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) { + warn!( + "Error while trying to garbage collect incremental \ compilation cache directory: {}", - e - ); - } - }); - } + e + ); + } + }); + } + + // Compute the dependency graph (in the background). We want to do + // this as early as possible, to give the DepGraph maximum time to + // load before dep_graph() is called, but it also can't happen + // until after rustc_incremental::prepare_session_directory() is + // called, which happens within passes::register_plugins(). + sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess)) + }); sess.time("recursion_limit", || { middle::recursion_limit::update_limits(sess, &krate); @@ -211,7 +225,7 @@ pub fn register_plugins<'a>( } }); - Ok((krate, Lrc::new(lint_store))) + (krate, Lrc::new(lint_store), dep_graph_future) } fn configure_and_expand_inner<'a>( diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index bd9717d3f3d02..a99d487c446ab 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -10,7 +10,9 @@ use rustc::ty::steal::Steal; use rustc::ty::{AllArenas, GlobalCtxt, ResolverOutputs}; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_data_structures::sync::future::Future; use rustc_data_structures::sync::{Lrc, Once, WorkerLocal}; +use rustc_data_structures::OnDrop; use rustc_hir::def_id::LOCAL_CRATE; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; @@ -69,10 +71,12 @@ pub struct Queries<'tcx> { all_arenas: AllArenas, arena: WorkerLocal>, - dep_graph_future: Query>, parse: Query, crate_name: Query, - register_plugins: Query<(ast::Crate, Lrc)>, + register_plugins: Query<( + Steal<(ast::Crate, Lrc)>, + Steal>>, + )>, expansion: Query<(ast::Crate, Steal>>, Lrc)>, dep_graph: Query, lower_to_hir: Query<(&'tcx map::Forest<'tcx>, Steal)>, @@ -88,7 +92,6 @@ impl<'tcx> Queries<'tcx> { gcx: Once::new(), all_arenas: AllArenas::new(), arena: WorkerLocal::new(|_| Arena::default()), - dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), register_plugins: Default::default(), @@ -108,16 +111,6 @@ impl<'tcx> Queries<'tcx> { &self.compiler.codegen_backend() } - pub fn dep_graph_future(&self) -> Result<&Query>> { - self.dep_graph_future.compute(|| { - Ok(self - .session() - .opts - .build_dep_graph() - .then(|| rustc_incremental::load_dep_graph(self.session()))) - }) - } - pub fn parse(&self) -> Result<&Query> { self.parse.compute(|| { passes::parse(self.session(), &self.compiler.input).map_err(|mut parse_error| { @@ -127,28 +120,27 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc)>> { + pub fn register_plugins( + &self, + ) -> Result< + &Query<( + Steal<(ast::Crate, Lrc)>, + Steal>>, + )>, + > { self.register_plugins.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {}; - let result = passes::register_plugins( + let (krate, lint_store, future) = passes::register_plugins( self.session(), &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_ref().map(|p| &**p).unwrap_or_else(|| empty), krate, - &crate_name, + crate_name, ); - - // Compute the dependency graph (in the background). We want to do - // this as early as possible, to give the DepGraph maximum time to - // load before dep_graph() is called, but it also can't happen - // until after rustc_incremental::prepare_session_directory() is - // called, which happens within passes::register_plugins(). - self.dep_graph_future().ok(); - - result + Ok((Steal::new((krate, lint_store)), Steal::new(future))) }) } @@ -174,7 +166,7 @@ impl<'tcx> Queries<'tcx> { ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); - let (krate, lint_store) = self.register_plugins()?.take(); + let (krate, lint_store) = self.register_plugins()?.peek().0.steal(); let _timer = self.session().timer("configure_and_expand"); passes::configure_and_expand( self.session().clone(), @@ -191,7 +183,8 @@ impl<'tcx> Queries<'tcx> { pub fn dep_graph(&self) -> Result<&Query> { self.dep_graph.compute(|| { - Ok(match self.dep_graph_future()?.take() { + let future = self.register_plugins()?.peek().1.steal().join(); + Ok(match future { None => DepGraph::new_disabled(), Some(future) => { let (prev_graph, prev_work_products) = @@ -336,6 +329,15 @@ impl Compiler { { let mut _timer = None; let queries = Queries::new(&self); + + // Join the dep graph future if has started, but haven't been stolen yet. + let _join_dep_graph_future = OnDrop(|| { + let result = queries.register_plugins.result.borrow_mut().take(); + result.map(|result| { + result.map(|result| result.1.into_inner().map(|future| future.join())) + }); + }); + let ret = f(&queries); if self.session().opts.debugging_opts.query_stats { From 3e2090c3ec9f825b6a570a5fac6a5ef4f07bc317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 14 Jan 2020 16:02:38 +0100 Subject: [PATCH 42/43] Check Session reference count --- src/librustc_interface/interface.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 9cd9eb66cf6c1..72eb86a0bbb8a 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -16,6 +16,7 @@ use rustc_lint::LintStore; use rustc_parse::new_parser_from_source_str; use rustc_span::edition; use rustc_span::source_map::{FileLoader, FileName, SourceMap}; +use std::mem; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -165,7 +166,7 @@ pub fn run_compiler_in_existing_thread_pool( registry.clone(), ); - let compiler = Compiler { + let mut compiler = Compiler { sess, codegen_backend, source_map, @@ -179,11 +180,20 @@ pub fn run_compiler_in_existing_thread_pool( }; let r = { - let _sess_abort_error = OnDrop(|| { + let sess_abort_error = OnDrop(|| { compiler.sess.diagnostic().print_error_count(registry); }); - f(&compiler) + let r = f(&compiler); + + mem::forget(sess_abort_error); + + // Ensure there are no more references to Session so no more errors can be generated. + Lrc::get_mut(&mut compiler.sess).expect("no references to Session"); + + compiler.sess.diagnostic().print_error_count(registry); + + r }; let prof = compiler.sess.prof.clone(); From a6ca4ffc38e372ab1b27e28f574b86d2bc733536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 7 Jan 2020 06:23:04 +0100 Subject: [PATCH 43/43] Run early lint checks in the background --- src/librustc_driver/lib.rs | 8 ++++++- src/librustc_interface/passes.rs | 36 +++++++++++++++++-------------- src/librustc_interface/queries.rs | 32 ++++++++++++++++----------- 3 files changed, 47 insertions(+), 29 deletions(-) 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()?;