Skip to content

Commit 3354a44

Browse files
committed
Auto merge of #87033 - FabianWolff:issue-87017, r=estebank
Provide a suggestion when trying to destructure a `Vec` as a slice Fixes #87017. r? `@estebank`
2 parents e91405b + 7b26f76 commit 3354a44

File tree

5 files changed

+110
-2
lines changed

5 files changed

+110
-2
lines changed

compiler/rustc_typeck/src/check/pat.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_span::lev_distance::find_best_match_for_name;
1616
use rustc_span::source_map::{Span, Spanned};
1717
use rustc_span::symbol::Ident;
1818
use rustc_span::{BytePos, DUMMY_SP};
19+
use rustc_trait_selection::autoderef::Autoderef;
1920
use rustc_trait_selection::traits::{ObligationCause, Pattern};
2021
use ty::VariantDef;
2122

@@ -1769,7 +1770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17691770
// The expected type must be an array or slice, but was neither, so error.
17701771
_ => {
17711772
if !expected.references_error() {
1772-
self.error_expected_array_or_slice(span, expected);
1773+
self.error_expected_array_or_slice(span, expected, ti);
17731774
}
17741775
let err = self.tcx.ty_error();
17751776
(err, Some(err), err)
@@ -1882,7 +1883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18821883
.emit();
18831884
}
18841885

1885-
fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>) {
1886+
fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
18861887
let mut err = struct_span_err!(
18871888
self.tcx.sess,
18881889
span,
@@ -1894,6 +1895,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18941895
if let ty::Array(..) | ty::Slice(..) = ty.kind() {
18951896
err.help("the semantics of slice patterns changed recently; see issue #62254");
18961897
}
1898+
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
1899+
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..)))
1900+
{
1901+
if let (Some(span), true) = (ti.span, ti.origin_expr) {
1902+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1903+
err.span_suggestion(
1904+
span,
1905+
"consider slicing here",
1906+
format!("{}[..]", snippet),
1907+
Applicability::MachineApplicable,
1908+
);
1909+
}
1910+
}
18971911
}
18981912
err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty));
18991913
err.emit();

src/test/ui/suggestions/match-ergonomics.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ LL | [&v] => {},
1515
error[E0529]: expected an array or slice, found `Vec<i32>`
1616
--> $DIR/match-ergonomics.rs:8:9
1717
|
18+
LL | match x {
19+
| - help: consider slicing here: `x[..]`
1820
LL | [&v] => {},
1921
| ^^^^ pattern cannot match with input type `Vec<i32>`
2022

2123
error[E0529]: expected an array or slice, found `Vec<i32>`
2224
--> $DIR/match-ergonomics.rs:20:9
2325
|
26+
LL | match x {
27+
| - help: consider slicing here: `x[..]`
2428
LL | [v] => {},
2529
| ^^^ pattern cannot match with input type `Vec<i32>`
2630

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Regression test for #87017.
2+
3+
// run-rustfix
4+
5+
fn main() {
6+
fn foo() -> Vec<i32> { vec![1, 2, 3] }
7+
8+
if let [_, _, _] = foo()[..] {}
9+
//~^ ERROR: expected an array or slice
10+
//~| HELP: consider slicing here
11+
12+
if let [] = &foo()[..] {}
13+
//~^ ERROR: expected an array or slice
14+
//~| HELP: consider slicing here
15+
16+
if let [] = foo()[..] {}
17+
//~^ ERROR: expected an array or slice
18+
//~| HELP: consider slicing here
19+
20+
let v = vec![];
21+
match &v[..] {
22+
//~^ HELP: consider slicing here
23+
[5] => {}
24+
//~^ ERROR: expected an array or slice
25+
_ => {}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Regression test for #87017.
2+
3+
// run-rustfix
4+
5+
fn main() {
6+
fn foo() -> Vec<i32> { vec![1, 2, 3] }
7+
8+
if let [_, _, _] = foo() {}
9+
//~^ ERROR: expected an array or slice
10+
//~| HELP: consider slicing here
11+
12+
if let [] = &foo() {}
13+
//~^ ERROR: expected an array or slice
14+
//~| HELP: consider slicing here
15+
16+
if let [] = foo() {}
17+
//~^ ERROR: expected an array or slice
18+
//~| HELP: consider slicing here
19+
20+
let v = vec![];
21+
match &v {
22+
//~^ HELP: consider slicing here
23+
[5] => {}
24+
//~^ ERROR: expected an array or slice
25+
_ => {}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0529]: expected an array or slice, found `Vec<i32>`
2+
--> $DIR/pattern-slice-vec.rs:8:12
3+
|
4+
LL | if let [_, _, _] = foo() {}
5+
| ^^^^^^^^^ ----- help: consider slicing here: `foo()[..]`
6+
| |
7+
| pattern cannot match with input type `Vec<i32>`
8+
9+
error[E0529]: expected an array or slice, found `Vec<i32>`
10+
--> $DIR/pattern-slice-vec.rs:12:12
11+
|
12+
LL | if let [] = &foo() {}
13+
| ^^ ------ help: consider slicing here: `&foo()[..]`
14+
| |
15+
| pattern cannot match with input type `Vec<i32>`
16+
17+
error[E0529]: expected an array or slice, found `Vec<i32>`
18+
--> $DIR/pattern-slice-vec.rs:16:12
19+
|
20+
LL | if let [] = foo() {}
21+
| ^^ ----- help: consider slicing here: `foo()[..]`
22+
| |
23+
| pattern cannot match with input type `Vec<i32>`
24+
25+
error[E0529]: expected an array or slice, found `Vec<_>`
26+
--> $DIR/pattern-slice-vec.rs:23:9
27+
|
28+
LL | match &v {
29+
| -- help: consider slicing here: `&v[..]`
30+
LL |
31+
LL | [5] => {}
32+
| ^^^ pattern cannot match with input type `Vec<_>`
33+
34+
error: aborting due to 4 previous errors
35+
36+
For more information about this error, try `rustc --explain E0529`.

0 commit comments

Comments
 (0)