diff options
| author | Fabian Wolff <fabian.wolff@alumni.ethz.ch> | 2021-07-10 19:54:48 +0200 |
|---|---|---|
| committer | Fabian Wolff <fabian.wolff@alumni.ethz.ch> | 2021-07-31 21:47:36 +0200 |
| commit | c29aadd9cf85d43249748228e858ae75d8edb768 (patch) | |
| tree | 1631ce63401395ed62bf906b3e6ba8cc0e999902 | |
| parent | 337181e07d3cd33c0aec2f17c12279bc9afca88f (diff) | |
| download | rust-c29aadd9cf85d43249748228e858ae75d8edb768.tar.gz rust-c29aadd9cf85d43249748228e858ae75d8edb768.zip | |
Provide a suggestion when trying to destructure a `Vec` as a slice
| -rw-r--r-- | compiler/rustc_typeck/src/check/pat.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/suggestions/match-ergonomics.stderr | 4 | ||||
| -rw-r--r-- | src/test/ui/suggestions/pattern-slice-vec.rs | 20 | ||||
| -rw-r--r-- | src/test/ui/suggestions/pattern-slice-vec.stderr | 28 |
4 files changed, 68 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 981a040e660..db77d155a2b 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -16,6 +16,7 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::Ident; use rustc_span::{BytePos, DUMMY_SP}; +use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::{ObligationCause, Pattern}; use ty::VariantDef; @@ -1769,7 +1770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The expected type must be an array or slice, but was neither, so error. _ => { if !expected.references_error() { - self.error_expected_array_or_slice(span, expected); + self.error_expected_array_or_slice(span, expected, ti); } let err = self.tcx.ty_error(); (err, Some(err), err) @@ -1882,7 +1883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } - fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>) { + fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>, ti: TopInfo<'tcx>) { let mut err = struct_span_err!( self.tcx.sess, span, @@ -1894,6 +1895,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Array(..) | ty::Slice(..) = ty.kind() { err.help("the semantics of slice patterns changed recently; see issue #62254"); } + } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) + .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..))) + { + if let (Some(span), true) = (ti.span, ti.origin_expr) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "consider slicing here", + format!("{}[..]", snippet), + Applicability::MachineApplicable, + ); + } + } } err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty)); err.emit(); diff --git a/src/test/ui/suggestions/match-ergonomics.stderr b/src/test/ui/suggestions/match-ergonomics.stderr index ca7562beb1f..4eab2df3080 100644 --- a/src/test/ui/suggestions/match-ergonomics.stderr +++ b/src/test/ui/suggestions/match-ergonomics.stderr @@ -15,12 +15,16 @@ LL | [&v] => {}, error[E0529]: expected an array or slice, found `Vec<i32>` --> $DIR/match-ergonomics.rs:8:9 | +LL | match x { + | - help: consider slicing here: `x[..]` LL | [&v] => {}, | ^^^^ pattern cannot match with input type `Vec<i32>` error[E0529]: expected an array or slice, found `Vec<i32>` --> $DIR/match-ergonomics.rs:20:9 | +LL | match x { + | - help: consider slicing here: `x[..]` LL | [v] => {}, | ^^^ pattern cannot match with input type `Vec<i32>` diff --git a/src/test/ui/suggestions/pattern-slice-vec.rs b/src/test/ui/suggestions/pattern-slice-vec.rs new file mode 100644 index 00000000000..1f010ae32a5 --- /dev/null +++ b/src/test/ui/suggestions/pattern-slice-vec.rs @@ -0,0 +1,20 @@ +// Regression test for #87017. + +fn main() { + fn foo() -> Vec<i32> { vec![1, 2, 3] } + + if let [_, _, _] = foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + if let [] = &foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + let v = vec![]; + match &v { + //~^ HELP: consider slicing here + [5] => {} + //~^ ERROR: expected an array or slice + _ => {} + } +} diff --git a/src/test/ui/suggestions/pattern-slice-vec.stderr b/src/test/ui/suggestions/pattern-slice-vec.stderr new file mode 100644 index 00000000000..a6337cc66bf --- /dev/null +++ b/src/test/ui/suggestions/pattern-slice-vec.stderr @@ -0,0 +1,28 @@ +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/pattern-slice-vec.rs:6:12 + | +LL | if let [_, _, _] = foo() {} + | ^^^^^^^^^ ----- help: consider slicing here: `foo()[..]` + | | + | pattern cannot match with input type `Vec<i32>` + +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/pattern-slice-vec.rs:9:12 + | +LL | if let [] = &foo() {} + | ^^ ------ help: consider slicing here: `&foo()[..]` + | | + | pattern cannot match with input type `Vec<i32>` + +error[E0529]: expected an array or slice, found `Vec<_>` + --> $DIR/pattern-slice-vec.rs:16:9 + | +LL | match &v { + | -- help: consider slicing here: `&v[..]` +LL | +LL | [5] => {} + | ^^^ pattern cannot match with input type `Vec<_>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0529`. |
