about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2022-09-07 02:37:18 +0900
committerTakayuki Maeda <takoyaki0316@gmail.com>2022-09-07 02:37:18 +0900
commit1e384423a9cfd678f976cf0183c81a770da2a325 (patch)
tree2cbd912b16f1b68b156f561906665ae88f4b4754
parentb44197abb0b3ffe4908892e1e08ab1cd721ff3b9 (diff)
downloadrust-1e384423a9cfd678f976cf0183c81a770da2a325.tar.gz
rust-1e384423a9cfd678f976cf0183c81a770da2a325.zip
suggest adding array lengths to references to arrays
-rw-r--r--compiler/rustc_hir/src/hir.rs8
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs47
-rw-r--r--src/test/ui/array-slice-vec/suggest-array-length.fixed12
-rw-r--r--src/test/ui/array-slice-vec/suggest-array-length.rs12
-rw-r--r--src/test/ui/array-slice-vec/suggest-array-length.stderr70
5 files changed, 120 insertions, 29 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 9535ccfe8b6..c17702d624a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2396,6 +2396,14 @@ impl<'hir> Ty<'hir> {
             _ => None,
         }
     }
+
+    pub fn peel_refs(&self) -> &Self {
+        let mut final_ty = self;
+        while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
+            final_ty = &ty;
+        }
+        final_ty
+    }
 }
 
 /// Not represented directly in the AST; referred to by name through a `ty_path`.
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index e4141647d7d..44f845bde61 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1305,31 +1305,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     fn suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64) {
-        if let Some(parent_hir_id) = self.tcx.hir().find_parent_node(expr.hir_id) {
-            let ty = match self.tcx.hir().find(parent_hir_id) {
-                Some(
-                    hir::Node::Local(hir::Local { ty: Some(ty), .. })
-                    | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }),
-                ) => Some(ty),
-                _ => None,
-            };
-            if let Some(ty) = ty
-                && let hir::TyKind::Array(_, length) = ty.kind
-                && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
-                && let Some(span) = self.tcx.hir().opt_span(hir_id)
-            {
-                match self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
-                    Some(mut err) => {
-                        err.span_suggestion(
-                            span,
-                            "consider specifying the array length",
-                            array_len,
-                            Applicability::MaybeIncorrect,
-                        );
-                        err.emit();
-                    }
-                    None => ()
+        let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| {
+            !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }))
+        });
+        let Some((_,
+            hir::Node::Local(hir::Local { ty: Some(ty), .. })
+            | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }))
+        ) = parent_node else {
+            return
+        };
+        if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
+            && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
+            && let Some(span) = self.tcx.hir().opt_span(hir_id)
+        {
+            match self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
+                Some(mut err) => {
+                    err.span_suggestion(
+                        span,
+                        "consider specifying the array length",
+                        array_len,
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.emit();
                 }
+                None => ()
             }
         }
     }
diff --git a/src/test/ui/array-slice-vec/suggest-array-length.fixed b/src/test/ui/array-slice-vec/suggest-array-length.fixed
index bae3ab74af6..867c18a7d5e 100644
--- a/src/test/ui/array-slice-vec/suggest-array-length.fixed
+++ b/src/test/ui/array-slice-vec/suggest-array-length.fixed
@@ -5,10 +5,22 @@ fn main() {
     const Foo: [i32; 3] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    const REF_FOO: &[u8; 1] = &[1];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
     let foo: [i32; 3] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
     let bar: [i32; 3] = [0; 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    let ref_foo: &[i32; 3] = &[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let ref_bar: &[i32; 3] = &[0; 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let multiple_ref_foo: &&[i32; 3] = &&[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
 }
diff --git a/src/test/ui/array-slice-vec/suggest-array-length.rs b/src/test/ui/array-slice-vec/suggest-array-length.rs
index b0867f4e396..f66b3d4a899 100644
--- a/src/test/ui/array-slice-vec/suggest-array-length.rs
+++ b/src/test/ui/array-slice-vec/suggest-array-length.rs
@@ -5,10 +5,22 @@ fn main() {
     const Foo: [i32; _] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    const REF_FOO: &[u8; _] = &[1];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
     let foo: [i32; _] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
     let bar: [i32; _] = [0; 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    let ref_foo: &[i32; _] = &[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let ref_bar: &[i32; _] = &[0; 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
 }
diff --git a/src/test/ui/array-slice-vec/suggest-array-length.stderr b/src/test/ui/array-slice-vec/suggest-array-length.stderr
index 9000f716028..16c90a04784 100644
--- a/src/test/ui/array-slice-vec/suggest-array-length.stderr
+++ b/src/test/ui/array-slice-vec/suggest-array-length.stderr
@@ -1,21 +1,45 @@
 error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:8:20
+  --> $DIR/suggest-array-length.rs:11:20
    |
 LL |     let foo: [i32; _] = [1, 2, 3];
    |                    ^ `_` not allowed here
 
 error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:11:20
+  --> $DIR/suggest-array-length.rs:14:20
    |
 LL |     let bar: [i32; _] = [0; 3];
    |                    ^ `_` not allowed here
 
 error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:17:25
+   |
+LL |     let ref_foo: &[i32; _] = &[1, 2, 3];
+   |                         ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:20:25
+   |
+LL |     let ref_bar: &[i32; _] = &[0; 3];
+   |                         ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:23:35
+   |
+LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
+   |                                   ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
   --> $DIR/suggest-array-length.rs:5:22
    |
 LL |     const Foo: [i32; _] = [1, 2, 3];
    |                      ^ `_` not allowed here
 
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:8:26
+   |
+LL |     const REF_FOO: &[u8; _] = &[1];
+   |                          ^ `_` not allowed here
+
 error[E0658]: using `_` for array lengths is unstable
   --> $DIR/suggest-array-length.rs:5:22
    |
@@ -26,7 +50,16 @@ LL |     const Foo: [i32; _] = [1, 2, 3];
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:8:20
+  --> $DIR/suggest-array-length.rs:8:26
+   |
+LL |     const REF_FOO: &[u8; _] = &[1];
+   |                          ^ help: consider specifying the array length: `1`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:11:20
    |
 LL |     let foo: [i32; _] = [1, 2, 3];
    |                    ^ help: consider specifying the array length: `3`
@@ -35,7 +68,7 @@ LL |     let foo: [i32; _] = [1, 2, 3];
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:11:20
+  --> $DIR/suggest-array-length.rs:14:20
    |
 LL |     let bar: [i32; _] = [0; 3];
    |                    ^ help: consider specifying the array length: `3`
@@ -43,6 +76,33 @@ LL |     let bar: [i32; _] = [0; 3];
    = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
 
-error: aborting due to 6 previous errors
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:17:25
+   |
+LL |     let ref_foo: &[i32; _] = &[1, 2, 3];
+   |                         ^ help: consider specifying the array length: `3`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:20:25
+   |
+LL |     let ref_bar: &[i32; _] = &[0; 3];
+   |                         ^ help: consider specifying the array length: `3`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:23:35
+   |
+LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
+   |                                   ^ help: consider specifying the array length: `3`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0658`.