From 56ad8bcfe0025618d35c8479797bca5d05e81099 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 2 Feb 2020 17:55:11 +0900 Subject: [PATCH] Do not suggest duplicate bounds --- src/librustc_typeck/check/method/suggest.rs | 42 ++++++++++--------- .../associated-item-duplicate-bounds.rs | 11 +++++ .../associated-item-duplicate-bounds.stderr | 11 +++++ src/test/ui/issues/issue-39559.stderr | 4 -- src/test/ui/span/issue-7575.stderr | 13 ++---- 5 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/associated-item/associated-item-duplicate-bounds.rs create mode 100644 src/test/ui/associated-item/associated-item-duplicate-bounds.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index e9942fad3bc..490c69b5536 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -853,26 +853,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { sp }; - // FIXME: contrast `t.def_id` against `param.bounds` to not suggest - // traits already there. That can happen when the cause is that - // we're in a const scope or associated function used as a method. - err.span_suggestions( - sp, - &message(format!( - "restrict type parameter `{}` with", - param.name.ident(), - )), - candidates.iter().map(|t| { - format!( - "{}{} {}{}", + let trait_def_ids: FxHashSet = param + .bounds + .iter() + .filter_map(|bound| bound.trait_def_id()) + .collect(); + if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) { + err.span_suggestions( + sp, + &message(format!( + "restrict type parameter `{}` with", param.name.ident(), - if impl_trait { " +" } else { ":" }, - self.tcx.def_path_str(t.def_id), - if has_bounds.is_some() { " + " } else { "" }, - ) - }), - Applicability::MaybeIncorrect, - ); + )), + candidates.iter().map(|t| { + format!( + "{}{} {}{}", + param.name.ident(), + if impl_trait { " +" } else { ":" }, + self.tcx.def_path_str(t.def_id), + if has_bounds.is_some() { " + " } else { "" }, + ) + }), + Applicability::MaybeIncorrect, + ); + } suggested = true; } Node::Item(hir::Item { diff --git a/src/test/ui/associated-item/associated-item-duplicate-bounds.rs b/src/test/ui/associated-item/associated-item-duplicate-bounds.rs new file mode 100644 index 00000000000..bec922b0721 --- /dev/null +++ b/src/test/ui/associated-item/associated-item-duplicate-bounds.rs @@ -0,0 +1,11 @@ +trait Adapter { + const LINKS: usize; +} + +struct Foo { + adapter: A, + links: [u32; A::LINKS], // Shouldn't suggest bounds already there. + //~^ ERROR: no associated item named `LINKS` found +} + +fn main() {} diff --git a/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr b/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr new file mode 100644 index 00000000000..ff1ad4c006e --- /dev/null +++ b/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr @@ -0,0 +1,11 @@ +error[E0599]: no associated item named `LINKS` found for type parameter `A` in the current scope + --> $DIR/associated-item-duplicate-bounds.rs:7:21 + | +LL | links: [u32; A::LINKS], // Shouldn't suggest bounds already there. + | ^^^^^ associated item not found in `A` + | + = help: items from traits can only be used if the type parameter is bounded by the trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr index 0554b232c24..5e8d487f416 100644 --- a/src/test/ui/issues/issue-39559.stderr +++ b/src/test/ui/issues/issue-39559.stderr @@ -5,10 +5,6 @@ LL | entries: [T; D::dim()], | ^^^ function or associated item not found in `D` | = help: items from traits can only be used if the type parameter is bounded by the trait -help: the following trait defines an item `dim`, perhaps you need to restrict type parameter `D` with it: - | -LL | pub struct Vector { - | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index eb85be039ba..89b36848a28 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -61,7 +61,10 @@ error[E0599]: no method named `is_str` found for type parameter `T` in the curre --> $DIR/issue-7575.rs:70:7 | LL | t.is_str() - | ^^^^^^ this is an associated function, not a method + | --^^^^^^-- + | | | + | | this is an associated function, not a method + | help: disambiguate the method call for the candidate: `ManyImplTrait::is_str(t)` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in the trait `ManyImplTrait` @@ -70,14 +73,6 @@ note: the candidate is defined in the trait `ManyImplTrait` LL | fn is_str() -> bool { | ^^^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the type parameter is bounded by the trait -help: disambiguate the method call for the candidate - | -LL | ManyImplTrait::is_str(t) - | -help: the following trait defines an item `is_str`, perhaps you need to restrict type parameter `T` with it: - | -LL | fn param_bound(t: T) -> bool { - | ^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors