From 472b416592f494aa4fe0db50802ba49803cec26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 1 Apr 2018 08:15:25 +0200 Subject: [PATCH] Querify all_traits --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/context.rs | 7 --- src/librustc/ty/maps/config.rs | 6 ++ src/librustc/ty/maps/mod.rs | 9 +++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_typeck/check/method/mod.rs | 5 ++ src/librustc_typeck/check/method/suggest.rs | 61 ++++++--------------- src/librustc_typeck/check/mod.rs | 1 + 8 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 7c5318a96f5a..663ac5b04f57 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -632,6 +632,7 @@ define_dep_nodes!( <'tcx> [input] MaybeUnusedTraitImport(DefId), [input] MaybeUnusedExternCrates, [eval_always] StabilityIndex, + [eval_always] AllTraits, [input] AllCrateNums, [] ExportedSymbols(CrateNum), [eval_always] CollectAndPartitionTranslationItems, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e6ad95ec3c77..677b7afc95a3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -898,12 +898,6 @@ pub struct GlobalCtxt<'tcx> { layout_interner: Lock>, - /// A vector of every trait accessible in the whole crate - /// (i.e. including those from subcrates). This is used only for - /// error reporting, and so is lazily initialized and generally - /// shouldn't taint the common path (hence the RefCell). - pub all_traits: RefCell>>, - /// A general purpose channel to throw data out the back towards LLVM worker /// threads. /// @@ -1283,7 +1277,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { derive_macros: RefCell::new(NodeMap()), stability_interner: Lock::new(FxHashSet()), interpret_interner: Default::default(), - all_traits: RefCell::new(None), tx_to_llvm_workers: Lock::new(tx), output_filenames: Arc::new(output_filenames.clone()), }; diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 16866636cd90..150328f2a6a3 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -586,6 +586,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::all_traits<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("fetching all foreign and local traits") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { format!("fetching all foreign CrateNum instances") diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 5a23a3b952a4..fd26855c9427 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -386,6 +386,11 @@ define_maps! { <'tcx> [] fn stability_index: stability_index_node(CrateNum) -> Lrc>, [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc>, + /// A vector of every trait accessible in the whole crate + /// (i.e. including those from subcrates). This is used only for + /// error reporting. + [] fn all_traits: all_traits_node(CrateNum) -> Lrc>, + [] fn exported_symbols: ExportedSymbols(CrateNum) -> Arc, SymbolExportLevel)>>, [] fn collect_and_partition_translation_items: @@ -575,6 +580,10 @@ fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::AllCrateNums } +fn all_traits_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::AllTraits +} + fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::CollectAndPartitionTranslationItems } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 232b300e7545..e812dd2d6c44 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -1115,6 +1115,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, } DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); } DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); } + DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); } DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); } DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); } DepKind::CollectAndPartitionTranslationItems => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e33e4c518924..49d0df555fa1 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -31,6 +31,7 @@ use rustc_data_structures::sync::Lrc; pub use self::MethodError::*; pub use self::CandidateSource::*; +pub use self::suggest::TraitInfo; mod confirm; pub mod probe; @@ -38,6 +39,10 @@ mod suggest; use self::probe::{IsSuggestion, ProbeScope}; +pub fn provide(providers: &mut ty::maps::Providers) { + suggest::provide(providers); +} + #[derive(Clone, Copy, Debug)] pub struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 4bc2d8ce123a..2dbc590bbf72 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -13,6 +13,7 @@ use check::FnCtxt; use rustc::hir::map as hir_map; +use rustc_data_structures::sync::Lrc; use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; use hir::def::Def; use hir::def_id::{CRATE_DEF_INDEX, DefId}; @@ -26,12 +27,12 @@ use syntax::util::lev_distance::find_best_match_for_name; use errors::DiagnosticBuilder; use syntax_pos::Span; +use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir; use rustc::hir::print; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::ty::TyAdt; -use std::cell; use std::cmp::Ordering; use super::{MethodError, NoMatchData, CandidateSource}; @@ -208,6 +209,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // be used exists at all, and the type is an ambiuous numeric type // ({integer}/{float}). let mut candidates = all_traits(self.tcx) + .into_iter() .filter(|info| { self.associated_item(info.def_id, item_name, Namespace::Value).is_some() }); @@ -519,6 +521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // implement, by finding ones that have the item name, and are // legal to implement. let mut candidates = all_traits(self.tcx) + .into_iter() .filter(|info| { // we approximate the coherence rules to only suggest // traits that are legal to implement by requiring that @@ -603,18 +606,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } -pub type AllTraitsVec = Vec; - #[derive(Copy, Clone)] pub struct TraitInfo { pub def_id: DefId, } -impl TraitInfo { - fn new(def_id: DefId) -> TraitInfo { - TraitInfo { def_id: def_id } - } -} impl PartialEq for TraitInfo { fn eq(&self, other: &TraitInfo) -> bool { self.cmp(other) == Ordering::Equal @@ -638,8 +634,12 @@ impl Ord for TraitInfo { } /// Retrieve all traits in this crate and any dependent crates. -pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> { - if tcx.all_traits.borrow().is_none() { +pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec { + tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect() +} + +/// Compute all traits in this crate and any dependent crates. +fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec { use rustc::hir::itemlikevisit; let mut traits = vec![]; @@ -649,7 +649,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> // meh. struct Visitor<'a, 'tcx: 'a> { map: &'a hir_map::Map<'tcx>, - traits: &'a mut AllTraitsVec, + traits: &'a mut Vec, } impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> { fn visit_item(&mut self, i: &'v hir::Item) { @@ -676,7 +676,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> // Cross-crate: let mut external_mods = FxHashSet(); fn handle_external_def(tcx: TyCtxt, - traits: &mut AllTraitsVec, + traits: &mut Vec, external_mods: &mut FxHashSet, def: Def) { let def_id = def.def_id(); @@ -703,43 +703,16 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id)); } - *tcx.all_traits.borrow_mut() = Some(traits); - } - - let borrow = tcx.all_traits.borrow(); - assert!(borrow.is_some()); - AllTraits { - borrow, - idx: 0, - } + traits } -pub struct AllTraits<'a> { - borrow: cell::Ref<'a, Option>, - idx: usize, -} - -impl<'a> Iterator for AllTraits<'a> { - type Item = TraitInfo; - - fn next(&mut self) -> Option { - let AllTraits { ref borrow, ref mut idx } = *self; - // ugh. - borrow.as_ref().unwrap().get(*idx).map(|info| { - *idx += 1; - TraitInfo::new(*info) - }) - } - - fn size_hint(&self) -> (usize, Option) { - let len = self.borrow.as_ref().unwrap().len() - self.idx; - (len, Some(len)) +pub fn provide(providers: &mut ty::maps::Providers) { + providers.all_traits = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Lrc::new(compute_all_traits(tcx)) } } -impl<'a> ExactSizeIterator for AllTraits<'a> {} - - struct UsePlacementFinder<'a, 'tcx: 'a, 'gcx: 'tcx> { target_module: ast::NodeId, span: Option, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6c18f8d285d0..1308f9ef2cd0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -730,6 +730,7 @@ fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: De } pub fn provide(providers: &mut Providers) { + method::provide(providers); *providers = Providers { typeck_item_bodies, typeck_tables_of,