diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index f4351bfa84aed..6c21ed902d007 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let report_candidates = |span: Span,
                                  err: &mut Diagnostic,
-                                 mut sources: Vec<CandidateSource>,
+                                 sources: &mut Vec<CandidateSource>,
                                  sugg_span: Span| {
             sources.sort();
             sources.dedup();
@@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         match error {
             MethodError::NoMatch(NoMatchData {
-                static_candidates: static_sources,
+                static_candidates: mut static_sources,
                 unsatisfied_predicates,
                 out_of_scope_traits,
                 lev_candidate,
@@ -422,9 +422,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.help(&format!("try with `{}::{}`", ty_str, item_name,));
                     }
 
-                    report_candidates(span, &mut err, static_sources, sugg_span);
+                    report_candidates(span, &mut err, &mut static_sources, sugg_span);
                 } else if static_sources.len() > 1 {
-                    report_candidates(span, &mut err, static_sources, sugg_span);
+                    report_candidates(span, &mut err, &mut static_sources, sugg_span);
                 }
 
                 let mut bound_spans = vec![];
@@ -1007,6 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         source,
                         out_of_scope_traits,
                         &unsatisfied_predicates,
+                        &static_sources,
                         unsatisfied_bounds,
                     );
                 }
@@ -1079,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return Some(err);
             }
 
-            MethodError::Ambiguity(sources) => {
+            MethodError::Ambiguity(mut sources) => {
                 let mut err = struct_span_err!(
                     self.sess(),
                     item_name.span,
@@ -1088,7 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
                 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
 
-                report_candidates(span, &mut err, sources, sugg_span);
+                report_candidates(span, &mut err, &mut sources, sugg_span);
                 err.emit();
             }
 
@@ -2015,6 +2016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Option<ty::Predicate<'tcx>>,
             Option<ObligationCause<'tcx>>,
         )],
+        static_candidates: &[CandidateSource],
         unsatisfied_bounds: bool,
     ) {
         let mut alt_rcvr_sugg = false;
@@ -2128,6 +2130,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(attr) => attr.level.is_stable(),
                 None => true,
             })
+            .filter(|info| {
+                // Static candidates are already implemented, and known not to work
+                // Do not suggest them again
+                static_candidates.iter().all(|sc| match *sc {
+                    CandidateSource::Trait(def_id) => def_id != info.def_id,
+                    CandidateSource::Impl(def_id) => {
+                        self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
+                    }
+                })
+            })
             .filter(|info| {
                 // We approximate the coherence rules to only suggest
                 // traits that are legal to implement by requiring that
diff --git a/src/test/ui/suggestions/issue-102354.rs b/src/test/ui/suggestions/issue-102354.rs
new file mode 100644
index 0000000000000..f881feb0060ab
--- /dev/null
+++ b/src/test/ui/suggestions/issue-102354.rs
@@ -0,0 +1,10 @@
+trait Trait {
+    fn func() {}
+}
+
+impl Trait for i32 {}
+
+fn main() {
+    let x: i32 = 123;
+    x.func(); //~ERROR no method
+}
diff --git a/src/test/ui/suggestions/issue-102354.stderr b/src/test/ui/suggestions/issue-102354.stderr
new file mode 100644
index 0000000000000..4f76c5f2e75b2
--- /dev/null
+++ b/src/test/ui/suggestions/issue-102354.stderr
@@ -0,0 +1,24 @@
+error[E0599]: no method named `func` found for type `i32` in the current scope
+  --> $DIR/issue-102354.rs:9:7
+   |
+LL |     x.func();
+   |       ^^^^ this is an associated function, not a method
+   |
+   = 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 `Trait`
+  --> $DIR/issue-102354.rs:2:5
+   |
+LL |     fn func() {}
+   |     ^^^^^^^^^
+help: use associated function syntax instead
+   |
+LL |     i32::func();
+   |     ~~~~~~~~~
+help: disambiguate the associated function for the candidate
+   |
+LL |     <i32 as Trait>::func(x);
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.