about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2015-12-17 23:58:56 +0100
committerFlorian Hahn <flo@fhahn.com>2016-01-02 19:47:02 +0100
commitba24fbd404d7489298af68b4384d1544cd54844d (patch)
tree870ac10b68adeae7d5d3193cf785b1110ecf6f85
parent6093ea8039d4bf48ef2b34ca0ec1397016bb2b52 (diff)
downloadrust-ba24fbd404d7489298af68b4384d1544cd54844d.tar.gz
rust-ba24fbd404d7489298af68b4384d1544cd54844d.zip
Manually check trait implementations
-rw-r--r--src/librustc/middle/traits/error_reporting.rs43
1 files changed, 31 insertions, 12 deletions
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index ef898221956..f4235f3df21 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -27,6 +27,7 @@ use fmt_macros::{Parser, Piece, Position};
 use middle::def_id::DefId;
 use middle::infer::InferCtxt;
 use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef, Ty};
+use middle::ty::fast_reject;
 use middle::ty::fold::TypeFoldable;
 use util::nodemap::{FnvHashMap, FnvHashSet};
 
@@ -233,20 +234,38 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                             if let Some(s) = custom_note {
                                 err.fileline_note(obligation.cause.span, &s);
                             } else {
-                                let mut impl_candidates = Vec::new();
-                                infcx.tcx.lookup_trait_def(trait_ref.def_id())
-                                         .for_each_relevant_impl(
-                                    infcx.tcx,
-                                    trait_ref.self_ty(),
-                                    |impl_def_id| {
-                                        match infcx.tcx.impl_trait_ref(impl_def_id) {
-                                            Some(ref imp) => {
-                                                impl_candidates.push(format!("  {}", imp));
-                                            },
-                                            None => (),
+                                infcx.tcx.populate_implementations_for_trait_if_necessary(
+                                    trait_ref.def_id());
+
+                                let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
+                                let blanket_impls = trait_def.blanket_impls.borrow();
+                                let impl_iter = blanket_impls.iter()
+                                                             .filter_map(|&id|
+                                                                     infcx.tcx.impl_trait_ref(id));
+
+                                let nonblanket = trait_def.nonblanket_impls.borrow();
+                                let nonblanket_iter = nonblanket.values()
+                                                            .flat_map(|ids|
+                                                                ids.iter().filter_map(|&id|
+                                                                    infcx.tcx.impl_trait_ref(id)));
+
+                                let simp = fast_reject::simplify_type(infcx.tcx, trait_ref.self_ty(), true);
+                                let nonblanket_iter = nonblanket_iter.filter(|def| {
+                                    if let Some(simp) = simp {
+                                        let imp_simp = fast_reject::simplify_type(infcx.tcx, def.self_ty(), true);
+                                        if let Some(imp_simp) = imp_simp {
+                                            simp == imp_simp
+                                        } else {
+                                            false
                                         }
+                                    } else {
+                                        true
                                     }
-                                );
+                                });
+
+                                let impl_candidates = impl_iter.chain(nonblanket_iter)
+                                                               .map(|imp| format!("  {}", imp))
+                                                               .take(5).collect::<Vec<_>>();
 
                                 if impl_candidates.len() > 0 {
                                     err.fileline_help(