Skip to content

Commit cae9267

Browse files
committed
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.
2 parents 4744472 + a8d6070 commit cae9267

File tree

4 files changed

+164
-2
lines changed

4 files changed

+164
-2
lines changed

src/librustc/middle/traits/error_reporting.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ 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

34+
use std::cmp;
3335
use std::fmt;
3436
use syntax::attr::{AttributeMethods, AttrMetaMethods};
3537
use syntax::codemap::Span;
@@ -231,12 +233,53 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
231233
obligation.cause.span);
232234
if let Some(s) = custom_note {
233235
err.fileline_note(obligation.cause.span, &s);
236+
} else {
237+
let simp = fast_reject::simplify_type(infcx.tcx,
238+
trait_ref.self_ty(),
239+
true);
240+
let mut impl_candidates = Vec::new();
241+
let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
242+
243+
match simp {
244+
Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| {
245+
let imp = infcx.tcx.impl_trait_ref(def_id).unwrap();
246+
let imp_simp = fast_reject::simplify_type(infcx.tcx,
247+
imp.self_ty(),
248+
true);
249+
if let Some(imp_simp) = imp_simp {
250+
if simp != imp_simp {
251+
return;
252+
}
253+
}
254+
impl_candidates.push(imp);
255+
}),
256+
None => trait_def.for_each_impl(infcx.tcx, |def_id| {
257+
impl_candidates.push(
258+
infcx.tcx.impl_trait_ref(def_id).unwrap());
259+
})
260+
};
261+
262+
if impl_candidates.len() > 0 {
263+
err.fileline_help(
264+
obligation.cause.span,
265+
&format!("the following implementations were found:"));
266+
267+
let end = cmp::min(4, impl_candidates.len());
268+
for candidate in &impl_candidates[0..end] {
269+
err.fileline_help(obligation.cause.span,
270+
&format!(" {:?}", candidate));
271+
}
272+
if impl_candidates.len() > 4 {
273+
err.fileline_help(obligation.cause.span,
274+
&format!("and {} others",
275+
impl_candidates.len()-4));
276+
}
277+
}
234278
}
235279
note_obligation_cause(infcx, &mut err, obligation);
236280
err.emit();
237281
}
238-
}
239-
282+
},
240283
ty::Predicate::Equate(ref predicate) => {
241284
let predicate = infcx.resolve_type_vars_if_possible(predicate);
242285
let err = infcx.equality_predicate(obligation.cause.span,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Foo<A> {
12+
fn foo(&self, a: A) -> A {
13+
a
14+
}
15+
}
16+
17+
trait NotRelevant<A> {
18+
fn nr(&self, a: A) -> A {
19+
a
20+
}
21+
}
22+
23+
struct Bar;
24+
25+
impl Foo<i32> for Bar {}
26+
27+
impl Foo<u8> for Bar {}
28+
29+
impl NotRelevant<usize> for Bar {}
30+
31+
fn main() {
32+
let f1 = Bar;
33+
34+
f1.foo(1usize);
35+
//~^ error: the trait `Foo<usize>` is not implemented for the type `Bar`
36+
// | help: the following implementations were found:
37+
// | help: implementation 1: `Foo<i32>`
38+
// | help: implementation 2: `Foo<u8>`
39+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Foo<A> {
12+
fn foo(&self, a: A) -> A {
13+
a
14+
}
15+
}
16+
17+
trait NotRelevant<A> {
18+
fn nr(&self, a: A) -> A {
19+
a
20+
}
21+
}
22+
23+
struct Bar;
24+
25+
impl Foo<i8> for Bar {}
26+
impl Foo<i16> for Bar {}
27+
impl Foo<i32> for Bar {}
28+
29+
impl Foo<u8> for Bar {}
30+
impl Foo<u16> for Bar {}
31+
impl Foo<u32> for Bar {}
32+
33+
impl NotRelevant<usize> for Bar {}
34+
35+
fn main() {
36+
let f1 = Bar;
37+
38+
f1.foo(1usize);
39+
//~^ error: the trait `Foo<usize>` is not implemented for the type `Bar`
40+
// | help: the following implementations were found:
41+
// | help: Foo<i8>
42+
// | help: Foo<i16>
43+
// | help: Foo<i32>
44+
// | help: Foo<u8>
45+
// | help: and 2 others
46+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Foo<A> {
12+
fn foo(&self, a: A) -> A {
13+
a
14+
}
15+
}
16+
17+
trait NotRelevant<A> {
18+
fn nr(&self, a: A) -> A {
19+
a
20+
}
21+
}
22+
23+
struct Bar;
24+
25+
impl NotRelevant<usize> for Bar {}
26+
27+
fn main() {
28+
let f1 = Bar;
29+
30+
f1.foo(1usize);
31+
//~^ error: method named `foo` found for type `Bar` in the current scope
32+
//~| help: items from traits can only be used if the trait is implemented and in scope
33+
//~| help: candidate #1: `Foo`
34+
}

0 commit comments

Comments
 (0)