Skip to content

Commit 121b911

Browse files
authored
Rollup merge of rust-lang#107173 - clubby789:suggest-array-length, r=compiler-errors
Suggest the correct array length on mismatch Fixes rust-lang#107156 I wasn't able to find a way to get the `Span` for the actual array size unfortunately, so this suggestion can't be applied automatically. `@rustbot` label +A-diagnostics
2 parents 85ad2af + 903ca87 commit 121b911

File tree

6 files changed

+119
-2
lines changed

6 files changed

+119
-2
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+65
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
6464
use rustc_hir as hir;
6565
use rustc_hir::def::DefKind;
6666
use rustc_hir::def_id::{DefId, LocalDefId};
67+
use rustc_hir::intravisit::Visitor;
6768
use rustc_hir::lang_items::LangItem;
6869
use rustc_hir::Node;
6970
use rustc_middle::dep_graph::DepContext;
@@ -1985,6 +1986,70 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
19851986
(ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
19861987
self.suggest_let_for_letchains(&mut err, &trace.cause, span);
19871988
}
1989+
(ty::Array(_, _), ty::Array(_, _)) => 'block: {
1990+
let hir = self.tcx.hir();
1991+
let TypeError::FixedArraySize(sz) = terr else {
1992+
break 'block;
1993+
};
1994+
let tykind = match hir.find_by_def_id(trace.cause.body_id) {
1995+
Some(hir::Node::Item(hir::Item {
1996+
kind: hir::ItemKind::Fn(_, _, body_id),
1997+
..
1998+
})) => {
1999+
let body = hir.body(*body_id);
2000+
struct LetVisitor<'v> {
2001+
span: Span,
2002+
result: Option<&'v hir::Ty<'v>>,
2003+
}
2004+
impl<'v> Visitor<'v> for LetVisitor<'v> {
2005+
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
2006+
if self.result.is_some() {
2007+
return;
2008+
}
2009+
// Find a local statement where the initializer has
2010+
// the same span as the error and the type is specified.
2011+
if let hir::Stmt {
2012+
kind: hir::StmtKind::Local(hir::Local {
2013+
init: Some(hir::Expr {
2014+
span: init_span,
2015+
..
2016+
}),
2017+
ty: Some(array_ty),
2018+
..
2019+
}),
2020+
..
2021+
} = s
2022+
&& init_span == &self.span {
2023+
self.result = Some(*array_ty);
2024+
}
2025+
}
2026+
}
2027+
let mut visitor = LetVisitor {span, result: None};
2028+
visitor.visit_body(body);
2029+
visitor.result.map(|r| &r.peel_refs().kind)
2030+
}
2031+
Some(hir::Node::Item(hir::Item {
2032+
kind: hir::ItemKind::Const(ty, _),
2033+
..
2034+
})) => {
2035+
Some(&ty.peel_refs().kind)
2036+
}
2037+
_ => None
2038+
};
2039+
2040+
if let Some(tykind) = tykind
2041+
&& let hir::TyKind::Array(_, length) = tykind
2042+
&& let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
2043+
&& let Some(span) = self.tcx.hir().opt_span(*hir_id)
2044+
{
2045+
err.span_suggestion(
2046+
span,
2047+
"consider specifying the actual array length",
2048+
sz.found,
2049+
Applicability::MaybeIncorrect,
2050+
);
2051+
}
2052+
}
19882053
_ => {}
19892054
}
19902055
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const NUMBERS: [u8; 3] = [10, 20];
2+
//~^ ERROR mismatched types
3+
//~^^ HELP consider specifying the actual array length
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/array-literal-len-mismatch.rs:1:26
3+
|
4+
LL | const NUMBERS: [u8; 3] = [10, 20];
5+
| - ^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
6+
| |
7+
| help: consider specifying the actual array length: `2`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0308`.

tests/ui/consts/const-array-oob-arith.stderr

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ error[E0308]: mismatched types
22
--> $DIR/const-array-oob-arith.rs:5:45
33
|
44
LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
5-
| ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
5+
| ---------------------- ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
6+
| |
7+
| help: consider specifying the actual array length: `1`
68

79
error[E0308]: mismatched types
810
--> $DIR/const-array-oob-arith.rs:8:44
911
|
1012
LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
11-
| ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
13+
| ---------------------- ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
14+
| |
15+
| help: consider specifying the actual array length: `2`
1216

1317
error: aborting due to 2 previous errors
1418

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn returns_arr() -> [u8; 2] {
2+
[1, 2]
3+
}
4+
5+
fn main() {
6+
let wrong: [u8; 3] = [10, 20];
7+
//~^ ERROR mismatched types
8+
//~^^ HELP consider specifying the actual array length
9+
let wrong: [u8; 3] = returns_arr();
10+
//~^ ERROR mismatched types
11+
//~^^ HELP consider specifying the actual array length
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/array-len-mismatch.rs:6:26
3+
|
4+
LL | let wrong: [u8; 3] = [10, 20];
5+
| ------- ^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
6+
| | |
7+
| | help: consider specifying the actual array length: `2`
8+
| expected due to this
9+
10+
error[E0308]: mismatched types
11+
--> $DIR/array-len-mismatch.rs:9:26
12+
|
13+
LL | let wrong: [u8; 3] = returns_arr();
14+
| ------- ^^^^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
15+
| | |
16+
| | help: consider specifying the actual array length: `2`
17+
| expected due to this
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)