diff options
| author | bors <bors@rust-lang.org> | 2016-01-03 19:14:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-01-03 19:14:20 +0000 |
| commit | cae9267d4735fa84cf7758b000ae1d64bdbac55c (patch) | |
| tree | 41fa100c1163ebd14edc4f206fcf95e1d89348ba /src | |
| parent | 4744472fe03cceb81747ac9c7c64ae5fe6340c0b (diff) | |
| parent | a8d60708ecabc90ca4b72e12483159339a0b40ce (diff) | |
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.
Diffstat (limited to 'src')
4 files changed, 164 insertions, 2 deletions
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 9193b1a09f9..038c414662a 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -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, diff --git a/src/test/compile-fail/issue-21659-show-relevant-trait-impls-1.rs b/src/test/compile-fail/issue-21659-show-relevant-trait-impls-1.rs new file mode 100644 index 00000000000..416eef4ad25 --- /dev/null +++ b/src/test/compile-fail/issue-21659-show-relevant-trait-impls-1.rs @@ -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>` +} diff --git a/src/test/compile-fail/issue-21659-show-relevant-trait-impls-2.rs b/src/test/compile-fail/issue-21659-show-relevant-trait-impls-2.rs new file mode 100644 index 00000000000..07a7c98dd7f --- /dev/null +++ b/src/test/compile-fail/issue-21659-show-relevant-trait-impls-2.rs @@ -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 +} diff --git a/src/test/compile-fail/issue-21659-show-relevant-trait-impls-3.rs b/src/test/compile-fail/issue-21659-show-relevant-trait-impls-3.rs new file mode 100644 index 00000000000..0bb944edb9d --- /dev/null +++ b/src/test/compile-fail/issue-21659-show-relevant-trait-impls-3.rs @@ -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` +} |
