about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-11-19 15:35:21 +0100
committerGitHub <noreply@github.com>2022-11-19 15:35:21 +0100
commite86f1845ff6ca556621e2d366a6ad0c2d5aa408f (patch)
treea0e0bf5061aff33ed74fa69ef9cf47c554e2d570
parent06707c073dcb29732933dc484877aa57c6dd1f94 (diff)
parent867582eb9710b08e88d45ca8d2a452efd3233fea (diff)
downloadrust-e86f1845ff6ca556621e2d366a6ad0c2d5aa408f.tar.gz
rust-e86f1845ff6ca556621e2d366a6ad0c2d5aa408f.zip
Rollup merge of #104497 - lyming2007:issue-104379-fix, r=fee1-dead
detect () to avoid redundant <> suggestion for type

fix #104379
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs6
-rw-r--r--compiler/rustc_span/src/source_map.rs25
-rw-r--r--src/test/ui/type/issue-103271.rs8
-rw-r--r--src/test/ui/type/issue-103271.stderr13
4 files changed, 44 insertions, 8 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 4ac4914bd44..9a66e73d9c2 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1918,12 +1918,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         | ty::Str
                         | ty::Projection(_)
                         | ty::Param(_) => format!("{deref_ty}"),
-                        // we need to test something like  <&[_]>::len
+                        // we need to test something like  <&[_]>::len or <(&[u32])>::len
                         // and Vec::function();
-                        // <&[_]>::len doesn't need an extra "<>" between
+                        // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
                         // but for Adt type like Vec::function()
                         // we would suggest <[_]>::function();
-                        _ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span)  => format!("{deref_ty}"),
+                        _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span)  => format!("{deref_ty}"),
                         _ => format!("<{deref_ty}>"),
                     };
                     err.span_suggestion_verbose(
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 7ea028b12ef..e8d129d733c 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -753,10 +753,11 @@ impl SourceMap {
         }
     }
 
-    /// Given a 'Span', tries to tell if the next character is '>'
-    /// and the previous charactoer is '<' after skipping white space
-    /// return true if wrapped by '<>'
-    pub fn span_wrapped_by_angle_bracket(&self, span: Span) -> bool {
+    /// Given a 'Span', tries to tell if it's wrapped by "<>" or "()"
+    /// the algorithm searches if the next character is '>' or ')' after skipping white space
+    /// then searches the previous charactoer to match '<' or '(' after skipping white space
+    /// return true if wrapped by '<>' or '()'
+    pub fn span_wrapped_by_angle_or_parentheses(&self, span: Span) -> bool {
         self.span_to_source(span, |src, start_index, end_index| {
             if src.get(start_index..end_index).is_none() {
                 return Ok(false);
@@ -764,11 +765,17 @@ impl SourceMap {
             // test the right side to match '>' after skipping white space
             let end_src = &src[end_index..];
             let mut i = 0;
+            let mut found_right_parentheses = false;
+            let mut found_right_angle = false;
             while let Some(cc) = end_src.chars().nth(i) {
                 if cc == ' ' {
                     i = i + 1;
                 } else if cc == '>' {
                     // found > in the right;
+                    found_right_angle = true;
+                    break;
+                } else if cc == ')' {
+                    found_right_parentheses = true;
                     break;
                 } else {
                     // failed to find '>' return false immediately
@@ -786,6 +793,16 @@ impl SourceMap {
                     i = i - 1;
                 } else if cc == '<' {
                     // found < in the left
+                    if !found_right_angle {
+                        // skip something like "(< )>"
+                        return Ok(false);
+                    }
+                    break;
+                } else if cc == '(' {
+                    if !found_right_parentheses {
+                        // skip something like "<(>)"
+                        return Ok(false);
+                    }
                     break;
                 } else {
                     // failed to find '<' return false immediately
diff --git a/src/test/ui/type/issue-103271.rs b/src/test/ui/type/issue-103271.rs
index bd3254af3df..7cd76286a92 100644
--- a/src/test/ui/type/issue-103271.rs
+++ b/src/test/ui/type/issue-103271.rs
@@ -7,4 +7,12 @@ fn main() {
         let x: &u32 = item;
         assert_eq!(x, &1);
     }
+    let iter_fun2 = <(&[u32])>::iter;
+    //~^ no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599]
+    //~| function or associated item not found in `&[u32]`
+    //~| HELP the function `iter` is implemented on `[u32]`
+    for item2 in iter_fun2(&[1,1]) {
+        let x: &u32 = item2;
+        assert_eq!(x, &1);
+    }
 }
diff --git a/src/test/ui/type/issue-103271.stderr b/src/test/ui/type/issue-103271.stderr
index 02a59d4b99c..f4dac51b2b4 100644
--- a/src/test/ui/type/issue-103271.stderr
+++ b/src/test/ui/type/issue-103271.stderr
@@ -9,6 +9,17 @@ help: the function `iter` is implemented on `[u32]`
 LL |     let iter_fun = <[u32]>::iter;
    |                     ~~~~~
 
-error: aborting due to previous error
+error[E0599]: no function or associated item named `iter` found for reference `&[u32]` in the current scope
+  --> $DIR/issue-103271.rs:10:33
+   |
+LL |     let iter_fun2 = <(&[u32])>::iter;
+   |                                 ^^^^ function or associated item not found in `&[u32]`
+   |
+help: the function `iter` is implemented on `[u32]`
+   |
+LL |     let iter_fun2 = <([u32])>::iter;
+   |                       ~~~~~
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0599`.