Auto merge of #29949 - fhahn:issue-21659-show-relevant-trait-impls, r=arielb1

This PR for #21659 uses `DefId.for_each_relevant_impl()` to show other possible implementations in the "trait not implemented" message.
This commit is contained in:
bors 2016-01-03 19:14:20 +00:00
commit cae9267d47
4 changed files with 164 additions and 2 deletions

View file

@ -27,9 +27,11 @@ 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};
use std::cmp;
use std::fmt;
use syntax::attr::{AttributeMethods, AttrMetaMethods};
use syntax::codemap::Span;
@ -231,12 +233,53 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
obligation.cause.span);
if let Some(s) = custom_note {
err.fileline_note(obligation.cause.span, &s);
} else {
let simp = fast_reject::simplify_type(infcx.tcx,
trait_ref.self_ty(),
true);
let mut impl_candidates = Vec::new();
let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
match simp {
Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| {
let imp = infcx.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(infcx.tcx,
imp.self_ty(),
true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
return;
}
}
impl_candidates.push(imp);
}),
None => trait_def.for_each_impl(infcx.tcx, |def_id| {
impl_candidates.push(
infcx.tcx.impl_trait_ref(def_id).unwrap());
})
};
if impl_candidates.len() > 0 {
err.fileline_help(
obligation.cause.span,
&format!("the following implementations were found:"));
let end = cmp::min(4, impl_candidates.len());
for candidate in &impl_candidates[0..end] {
err.fileline_help(obligation.cause.span,
&format!(" {:?}", candidate));
}
if impl_candidates.len() > 4 {
err.fileline_help(obligation.cause.span,
&format!("and {} others",
impl_candidates.len()-4));
}
}
}
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
}
}
},
ty::Predicate::Equate(ref predicate) => {
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.equality_predicate(obligation.cause.span,

View file

@ -0,0 +1,39 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo<A> {
fn foo(&self, a: A) -> A {
a
}
}
trait NotRelevant<A> {
fn nr(&self, a: A) -> A {
a
}
}
struct Bar;
impl Foo<i32> for Bar {}
impl Foo<u8> for Bar {}
impl NotRelevant<usize> for Bar {}
fn main() {
let f1 = Bar;
f1.foo(1usize);
//~^ error: the trait `Foo<usize>` is not implemented for the type `Bar`
// | help: the following implementations were found:
// | help: implementation 1: `Foo<i32>`
// | help: implementation 2: `Foo<u8>`
}

View file

@ -0,0 +1,46 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo<A> {
fn foo(&self, a: A) -> A {
a
}
}
trait NotRelevant<A> {
fn nr(&self, a: A) -> A {
a
}
}
struct Bar;
impl Foo<i8> for Bar {}
impl Foo<i16> for Bar {}
impl Foo<i32> for Bar {}
impl Foo<u8> for Bar {}
impl Foo<u16> for Bar {}
impl Foo<u32> for Bar {}
impl NotRelevant<usize> for Bar {}
fn main() {
let f1 = Bar;
f1.foo(1usize);
//~^ error: the trait `Foo<usize>` is not implemented for the type `Bar`
// | help: the following implementations were found:
// | help: Foo<i8>
// | help: Foo<i16>
// | help: Foo<i32>
// | help: Foo<u8>
// | help: and 2 others
}

View file

@ -0,0 +1,34 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo<A> {
fn foo(&self, a: A) -> A {
a
}
}
trait NotRelevant<A> {
fn nr(&self, a: A) -> A {
a
}
}
struct Bar;
impl NotRelevant<usize> for Bar {}
fn main() {
let f1 = Bar;
f1.foo(1usize);
//~^ error: method named `foo` found for type `Bar` in the current scope
//~| help: items from traits can only be used if the trait is implemented and in scope
//~| help: candidate #1: `Foo`
}