Skip to content

Commit ba24fbd

Browse files
committed
Manually check trait implementations
1 parent 6093ea8 commit ba24fbd

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

src/librustc/middle/traits/error_reporting.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use fmt_macros::{Parser, Piece, Position};
2727
use middle::def_id::DefId;
2828
use middle::infer::InferCtxt;
2929
use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef, Ty};
30+
use middle::ty::fast_reject;
3031
use middle::ty::fold::TypeFoldable;
3132
use util::nodemap::{FnvHashMap, FnvHashSet};
3233

@@ -233,20 +234,38 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
233234
if let Some(s) = custom_note {
234235
err.fileline_note(obligation.cause.span, &s);
235236
} else {
236-
let mut impl_candidates = Vec::new();
237-
infcx.tcx.lookup_trait_def(trait_ref.def_id())
238-
.for_each_relevant_impl(
239-
infcx.tcx,
240-
trait_ref.self_ty(),
241-
|impl_def_id| {
242-
match infcx.tcx.impl_trait_ref(impl_def_id) {
243-
Some(ref imp) => {
244-
impl_candidates.push(format!(" {}", imp));
245-
},
246-
None => (),
237+
infcx.tcx.populate_implementations_for_trait_if_necessary(
238+
trait_ref.def_id());
239+
240+
let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
241+
let blanket_impls = trait_def.blanket_impls.borrow();
242+
let impl_iter = blanket_impls.iter()
243+
.filter_map(|&id|
244+
infcx.tcx.impl_trait_ref(id));
245+
246+
let nonblanket = trait_def.nonblanket_impls.borrow();
247+
let nonblanket_iter = nonblanket.values()
248+
.flat_map(|ids|
249+
ids.iter().filter_map(|&id|
250+
infcx.tcx.impl_trait_ref(id)));
251+
252+
let simp = fast_reject::simplify_type(infcx.tcx, trait_ref.self_ty(), true);
253+
let nonblanket_iter = nonblanket_iter.filter(|def| {
254+
if let Some(simp) = simp {
255+
let imp_simp = fast_reject::simplify_type(infcx.tcx, def.self_ty(), true);
256+
if let Some(imp_simp) = imp_simp {
257+
simp == imp_simp
258+
} else {
259+
false
247260
}
261+
} else {
262+
true
248263
}
249-
);
264+
});
265+
266+
let impl_candidates = impl_iter.chain(nonblanket_iter)
267+
.map(|imp| format!(" {}", imp))
268+
.take(5).collect::<Vec<_>>();
250269

251270
if impl_candidates.len() > 0 {
252271
err.fileline_help(

0 commit comments

Comments
 (0)