about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/dep_graph/dep_node.rs1
-rw-r--r--src/librustc/ty/context.rs7
-rw-r--r--src/librustc/ty/maps/config.rs6
-rw-r--r--src/librustc/ty/maps/mod.rs9
-rw-r--r--src/librustc/ty/maps/plumbing.rs1
-rw-r--r--src/librustc_typeck/check/method/mod.rs5
-rw-r--r--src/librustc_typeck/check/method/suggest.rs61
-rw-r--r--src/librustc_typeck/check/mod.rs1
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 7c5318a96f5..663ac5b04f5 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 e6ad95ec3c7..677b7afc95a 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -898,12 +898,6 @@ pub struct GlobalCtxt<'tcx> {
 
     layout_interner: Lock<FxHashSet<&'tcx LayoutDetails>>,
 
-    /// 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<Option<Vec<DefId>>>,
-
     /// 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 16866636cd9..150328f2a6a 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 5a23a3b952a..fd26855c942 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<stability::Index<'tcx>>,
     [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
 
+    /// 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<Vec<DefId>>,
+
     [] fn exported_symbols: ExportedSymbols(CrateNum)
         -> Arc<Vec<(ExportedSymbol<'tcx>, 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 232b300e754..e812dd2d6c4 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 e33e4c51892..49d0df555fa 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 4bc2d8ce123..2dbc590bbf7 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<DefId>;
-
 #[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<TraitInfo> {
+    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<DefId> {
         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<DefId>,
         }
         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<DefId>,
                                external_mods: &mut FxHashSet<DefId>,
                                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<AllTraitsVec>>,
-    idx: usize,
-}
-
-impl<'a> Iterator for AllTraits<'a> {
-    type Item = TraitInfo;
-
-    fn next(&mut self) -> Option<TraitInfo> {
-        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<usize>) {
-        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<Span>,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 6c18f8d285d..1308f9ef2cd 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,