diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 056f9ca08f8..c1c7a7ddd91 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -48,7 +48,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability, Handler}; +use rustc_errors::{struct_span_err, Applicability, Handler, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -2235,7 +2235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { c.value.span, "using `_` for array lengths is unstable", ) - .emit(); + .stash(c.value.span, StashKey::UnderscoreForArrayLengths); hir::ArrayLen::Body(self.lower_anon_const(c)) } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index d2eb4f212eb..395bf5aad01 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -457,6 +457,7 @@ struct HandlerInner { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum StashKey { ItemNoType, + UnderscoreForArrayLengths, } fn default_track_diagnostic(_: &Diagnostic) {} diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 6a6c03a8cba..9c2fdd87516 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -28,7 +28,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, - ErrorGuaranteed, + ErrorGuaranteed, StashKey, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -1307,7 +1307,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: expr.span, }) }; - self.tcx.mk_array(element_ty, args.len() as u64) + let array_len = args.len() as u64; + self.suggest_array_len(expr, array_len); + self.tcx.mk_array(element_ty, array_len) + } + + 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 => () + } + } + } } fn check_expr_const_block( @@ -1333,10 +1365,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { element: &'tcx hir::Expr<'tcx>, count: &'tcx hir::ArrayLen, expected: Expectation<'tcx>, - _expr: &'tcx hir::Expr<'tcx>, + expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let count = self.array_length_to_const(count); + if let Some(count) = count.try_eval_usize(tcx, self.param_env) { + self.suggest_array_len(expr, count); + } let uty = match expected { ExpectHasType(uty) => match *uty.kind() { diff --git a/src/test/ui/array-slice-vec/suggest-array-length.fixed b/src/test/ui/array-slice-vec/suggest-array-length.fixed new file mode 100644 index 00000000000..bae3ab74af6 --- /dev/null +++ b/src/test/ui/array-slice-vec/suggest-array-length.fixed @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(unused_variables, dead_code, non_upper_case_globals)] + +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 + 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 +} diff --git a/src/test/ui/array-slice-vec/suggest-array-length.rs b/src/test/ui/array-slice-vec/suggest-array-length.rs new file mode 100644 index 00000000000..b0867f4e396 --- /dev/null +++ b/src/test/ui/array-slice-vec/suggest-array-length.rs @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(unused_variables, dead_code, non_upper_case_globals)] + +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 + 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 +} diff --git a/src/test/ui/array-slice-vec/suggest-array-length.stderr b/src/test/ui/array-slice-vec/suggest-array-length.stderr new file mode 100644 index 00000000000..9000f716028 --- /dev/null +++ b/src/test/ui/array-slice-vec/suggest-array-length.stderr @@ -0,0 +1,48 @@ +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:8: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 + | +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:5:22 + | +LL | const Foo: [i32; _] = [1, 2, 3]; + | ^ `_` not allowed here + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:5:22 + | +LL | const Foo: [i32; _] = [1, 2, 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #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:8:20 + | +LL | let foo: [i32; _] = [1, 2, 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #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 bar: [i32; _] = [0; 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/async-await/issues/issue-95307.stderr b/src/test/ui/async-await/issues/issue-95307.stderr index 60fca71eb4b..29aebb719d6 100644 --- a/src/test/ui/async-await/issues/issue-95307.stderr +++ b/src/test/ui/async-await/issues/issue-95307.stderr @@ -9,6 +9,12 @@ LL | async fn new() -> [u8; _]; = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/issue-95307.rs:7:28 + | +LL | async fn new() -> [u8; _]; + | ^ `_` not allowed here + error[E0658]: using `_` for array lengths is unstable --> $DIR/issue-95307.rs:7:28 | @@ -18,12 +24,6 @@ LL | async fn new() -> [u8; _]; = note: see issue #85077 for more information = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/issue-95307.rs:7:28 - | -LL | async fn new() -> [u8; _]; - | ^ `_` not allowed here - error: aborting due to 3 previous errors Some errors have detailed explanations: E0658, E0706. diff --git a/src/test/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr b/src/test/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr index 49eede4794b..56123a983b3 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr +++ b/src/test/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr @@ -1,33 +1,24 @@ -error[E0658]: using `_` for array lengths is unstable - --> $DIR/feature-gate-generic_arg_infer.rs:11:27 - | -LL | let _x: [u8; 3] = [0; _]; - | ^ - | - = note: see issue #85077 for more information - = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/feature-gate-generic_arg_infer.rs:11:27 | LL | let _x: [u8; 3] = [0; _]; | ^ `_` not allowed here -error[E0658]: using `_` for array lengths is unstable - --> $DIR/feature-gate-generic_arg_infer.rs:14:18 - | -LL | let _y: [u8; _] = [0; 3]; - | ^ - | - = note: see issue #85077 for more information - = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/feature-gate-generic_arg_infer.rs:14:18 | LL | let _y: [u8; _] = [0; 3]; | ^ `_` not allowed here +error[E0658]: using `_` for array lengths is unstable + --> $DIR/feature-gate-generic_arg_infer.rs:14:18 + | +LL | let _y: [u8; _] = [0; 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + error[E0747]: type provided when a constant was expected --> $DIR/feature-gate-generic_arg_infer.rs:20:20 | @@ -37,6 +28,15 @@ LL | let _x = foo::<_>([1,2]); = help: const arguments cannot yet be inferred with `_` = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable +error[E0658]: using `_` for array lengths is unstable + --> $DIR/feature-gate-generic_arg_infer.rs:11:27 + | +LL | let _x: [u8; 3] = [0; _]; + | ^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + error: aborting due to 5 previous errors Some errors have detailed explanations: E0658, E0747.