about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs6
-rw-r--r--compiler/rustc_span/src/source_map.rs44
-rw-r--r--src/test/ui/type/issue-103271.rs10
-rw-r--r--src/test/ui/type/issue-103271.stderr14
4 files changed, 74 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 04ecd2757b4..f41f8731867 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1804,6 +1804,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         | ty::Str
                         | ty::Projection(_)
                         | ty::Param(_) => format!("{deref_ty}"),
+                        // we need to test something like  <&[_]>::len
+                        // and Vec::function();
+                        // <&[_]>::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}"),
                         _ => 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 f9566eeee94..029cd93a52a 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -753,6 +753,50 @@ 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 {
+        self.span_to_source(span, |src, start_index, end_index| {
+            if src.get(start_index..end_index).is_none() {
+                return Ok(false);
+            }
+            // test the right side to match '>' after skipping white space
+            let end_src = &src[end_index..];
+            let mut i = 0;
+            while let Some(cc) = end_src.chars().nth(i) {
+                if cc == ' ' {
+                    i = i + 1;
+                } else if cc == '>' {
+                    // found > in the right;
+                    break;
+                } else {
+                    // failed to find '>' return false immediately
+                    return Ok(false);
+                }
+            }
+            // test the left side to match '<' after skipping white space
+            i = start_index;
+            let start_src = &src[0..start_index];
+            while let Some(cc) = start_src.chars().nth(i) {
+                if cc == ' ' {
+                    if i == 0 {
+                        return Ok(false);
+                    }
+                    i = i - 1;
+                } else if cc == '<' {
+                    // found < in the left
+                    break;
+                } else {
+                    // failed to find '<' return false immediately
+                    return Ok(false);
+                }
+            }
+            return Ok(true);
+        })
+        .map_or(false, |is_accessible| is_accessible)
+    }
+
     /// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
     /// `c`.
     pub fn span_through_char(&self, sp: Span, c: char) -> Span {
diff --git a/src/test/ui/type/issue-103271.rs b/src/test/ui/type/issue-103271.rs
new file mode 100644
index 00000000000..bd3254af3df
--- /dev/null
+++ b/src/test/ui/type/issue-103271.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let iter_fun = <&[u32]>::iter;
+    //~^ ERROR 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 item in iter_fun(&[1,1]) {
+        let x: &u32 = item;
+        assert_eq!(x, &1);
+    }
+}
diff --git a/src/test/ui/type/issue-103271.stderr b/src/test/ui/type/issue-103271.stderr
new file mode 100644
index 00000000000..02a59d4b99c
--- /dev/null
+++ b/src/test/ui/type/issue-103271.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no function or associated item named `iter` found for reference `&[u32]` in the current scope
+  --> $DIR/issue-103271.rs:2:30
+   |
+LL |     let iter_fun = <&[u32]>::iter;
+   |                              ^^^^ function or associated item not found in `&[u32]`
+   |
+help: the function `iter` is implemented on `[u32]`
+   |
+LL |     let iter_fun = <[u32]>::iter;
+   |                     ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.