From 2a229c96e8ca9cad46248555202619709fd3c2fe Mon Sep 17 00:00:00 2001
From: yukang <moorekang@gmail.com>
Date: Mon, 12 Feb 2024 21:05:39 +0800
Subject: [PATCH] remove importing suggestions when there is a shadowed typo
 canddiate

---
 .../rustc_resolve/src/late/diagnostics.rs     | 62 ++++++++++++-------
 tests/ui/resolve/issue-120559.rs              |  5 ++
 tests/ui/resolve/issue-120559.stderr          | 14 +++++
 tests/ui/span/issue-35987.stderr              |  5 --
 4 files changed, 58 insertions(+), 28 deletions(-)
 create mode 100644 tests/ui/resolve/issue-120559.rs
 create mode 100644 tests/ui/resolve/issue-120559.stderr

diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 5d712461993d8..cb3b95a443416 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -460,7 +460,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             return (err, Vec::new());
         }
 
-        let (found, candidates) = self.try_lookup_name_relaxed(
+        let (found, mut candidates) = self.try_lookup_name_relaxed(
             &mut err,
             source,
             path,
@@ -473,10 +473,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             return (err, candidates);
         }
 
-        let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
+        if self.suggest_shadowed(&mut err, source, path, following_seg, span) {
+            // if there is already a shadowed name, don'suggest candidates for importing
+            candidates.clear();
+        }
 
-        // if we have suggested using pattern matching, then don't add needless suggestions
-        // for typos.
+        let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
         fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error);
 
         if fallback {
@@ -872,25 +874,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
         let typo_sugg =
             self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
-        let is_in_same_file = &|sp1, sp2| {
-            let source_map = self.r.tcx.sess.source_map();
-            let file1 = source_map.span_to_filename(sp1);
-            let file2 = source_map.span_to_filename(sp2);
-            file1 == file2
-        };
-        // print 'you might have meant' if the candidate is (1) is a shadowed name with
-        // accessible definition and (2) either defined in the same crate as the typo
-        // (could be in a different file) or introduced in the same file as the typo
-        // (could belong to a different crate)
-        if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
-            && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
-        {
-            err.span_label(
-                sugg_span,
-                format!("you might have meant to refer to this {}", res.descr()),
-            );
-            return true;
-        }
         let mut fallback = false;
         let typo_sugg = typo_sugg.to_opt_suggestion();
         if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
@@ -918,6 +901,39 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         fallback
     }
 
+    fn suggest_shadowed(
+        &mut self,
+        err: &mut Diagnostic,
+        source: PathSource<'_>,
+        path: &[Segment],
+        following_seg: Option<&Segment>,
+        span: Span,
+    ) -> bool {
+        let is_expected = &|res| source.is_expected(res);
+        let typo_sugg =
+            self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
+        let is_in_same_file = &|sp1, sp2| {
+            let source_map = self.r.tcx.sess.source_map();
+            let file1 = source_map.span_to_filename(sp1);
+            let file2 = source_map.span_to_filename(sp2);
+            file1 == file2
+        };
+        // print 'you might have meant' if the candidate is (1) is a shadowed name with
+        // accessible definition and (2) either defined in the same crate as the typo
+        // (could be in a different file) or introduced in the same file as the typo
+        // (could belong to a different crate)
+        if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
+            && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
+        {
+            err.span_label(
+                sugg_span,
+                format!("you might have meant to refer to this {}", res.descr()),
+            );
+            return true;
+        }
+        false
+    }
+
     fn err_code_special_cases(
         &mut self,
         err: &mut Diagnostic,
diff --git a/tests/ui/resolve/issue-120559.rs b/tests/ui/resolve/issue-120559.rs
new file mode 100644
index 0000000000000..e874e840de785
--- /dev/null
+++ b/tests/ui/resolve/issue-120559.rs
@@ -0,0 +1,5 @@
+use std::io::Read;
+
+fn f<T: Read, U, Read>() {} //~ ERROR expected trait, found type parameter `Read`
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-120559.stderr b/tests/ui/resolve/issue-120559.stderr
new file mode 100644
index 0000000000000..9150fb38ad5ce
--- /dev/null
+++ b/tests/ui/resolve/issue-120559.stderr
@@ -0,0 +1,14 @@
+error[E0404]: expected trait, found type parameter `Read`
+  --> $DIR/issue-120559.rs:3:9
+   |
+LL | use std::io::Read;
+   |              ---- you might have meant to refer to this trait
+LL |
+LL | fn f<T: Read, U, Read>() {}
+   |         ^^^^     ---- found this type parameter
+   |         |
+   |         not a trait
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr
index 4c4b100da3dd8..d3014f276fd84 100644
--- a/tests/ui/span/issue-35987.stderr
+++ b/tests/ui/span/issue-35987.stderr
@@ -8,11 +8,6 @@ LL | impl<T: Clone, Add> Add for Foo<T> {
    |                ---  ^^^ not a trait
    |                |
    |                found this type parameter
-   |
-help: consider importing this trait instead
-   |
-LL + use std::ops::Add;
-   |
 
 error: aborting due to 1 previous error