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:
commit
cae9267d47
4 changed files with 164 additions and 2 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>`
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue