Skip to content

Commit

Permalink
Rollup merge of rust-lang#91343 - FabianWolff:issue-91328-as-deref, r…
Browse files Browse the repository at this point in the history
…=jackh726

Fix suggestion to slice if scrutinee is a `Result` or `Option`

Fixes rust-lang#91328.
  • Loading branch information
matthiaskrgr authored Jan 31, 2022
2 parents 498eeb7 + 95344c0 commit a937dd5
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 7 deletions.
41 changes: 34 additions & 7 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::hygiene::DesugaringKind;
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::symbol::{sym, Ident};
use rustc_span::{BytePos, MultiSpan, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::{ObligationCause, Pattern};
Expand Down Expand Up @@ -2033,12 +2033,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
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,
);
let applicability = match self.resolve_vars_if_possible(ti.expected).kind() {
ty::Adt(adt_def, _)
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
{
// Slicing won't work here, but `.as_deref()` might (issue #91328).
err.span_suggestion(
span,
"consider using `as_deref` here",
format!("{}.as_deref()", snippet),
Applicability::MaybeIncorrect,
);
None
}
// FIXME: instead of checking for Vec only, we could check whether the
// type implements `Deref<Target=X>`; see
// https://github.com/rust-lang/rust/pull/91343#discussion_r761466979
ty::Adt(adt_def, _)
if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) =>
{
Some(Applicability::MachineApplicable)
}
_ => Some(Applicability::MaybeIncorrect),
};

if let Some(applicability) = applicability {
err.span_suggestion(
span,
"consider slicing here",
format!("{}[..]", snippet),
applicability,
);
}
}
}
}
Expand Down
37 changes: 37 additions & 0 deletions src/test/ui/typeck/issue-91328.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Regression test for issue #91328.

// run-rustfix

#![allow(dead_code)]

fn foo(r: Result<Vec<i32>, i32>) -> i32 {
match r.as_deref() {
//~^ HELP: consider using `as_deref` here
Ok([a, b]) => a + b,
//~^ ERROR: expected an array or slice
//~| NOTE: pattern cannot match with input type
_ => 42,
}
}

fn bar(o: Option<Vec<i32>>) -> i32 {
match o.as_deref() {
//~^ HELP: consider using `as_deref` here
Some([a, b]) => a + b,
//~^ ERROR: expected an array or slice
//~| NOTE: pattern cannot match with input type
_ => 42,
}
}

fn baz(v: Vec<i32>) -> i32 {
match v[..] {
//~^ HELP: consider slicing here
[a, b] => a + b,
//~^ ERROR: expected an array or slice
//~| NOTE: pattern cannot match with input type
_ => 42,
}
}

fn main() {}
37 changes: 37 additions & 0 deletions src/test/ui/typeck/issue-91328.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Regression test for issue #91328.

// run-rustfix

#![allow(dead_code)]

fn foo(r: Result<Vec<i32>, i32>) -> i32 {
match r {
//~^ HELP: consider using `as_deref` here
Ok([a, b]) => a + b,
//~^ ERROR: expected an array or slice
//~| NOTE: pattern cannot match with input type
_ => 42,
}
}

fn bar(o: Option<Vec<i32>>) -> i32 {
match o {
//~^ HELP: consider using `as_deref` here
Some([a, b]) => a + b,
//~^ ERROR: expected an array or slice
//~| NOTE: pattern cannot match with input type
_ => 42,
}
}

fn baz(v: Vec<i32>) -> i32 {
match v {
//~^ HELP: consider slicing here
[a, b] => a + b,
//~^ ERROR: expected an array or slice
//~| NOTE: pattern cannot match with input type
_ => 42,
}
}

fn main() {}
30 changes: 30 additions & 0 deletions src/test/ui/typeck/issue-91328.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error[E0529]: expected an array or slice, found `Vec<i32>`
--> $DIR/issue-91328.rs:10:12
|
LL | match r {
| - help: consider using `as_deref` here: `r.as_deref()`
LL |
LL | Ok([a, b]) => a + b,
| ^^^^^^ pattern cannot match with input type `Vec<i32>`

error[E0529]: expected an array or slice, found `Vec<i32>`
--> $DIR/issue-91328.rs:20:14
|
LL | match o {
| - help: consider using `as_deref` here: `o.as_deref()`
LL |
LL | Some([a, b]) => a + b,
| ^^^^^^ pattern cannot match with input type `Vec<i32>`

error[E0529]: expected an array or slice, found `Vec<i32>`
--> $DIR/issue-91328.rs:30:9
|
LL | match v {
| - help: consider slicing here: `v[..]`
LL |
LL | [a, b] => a + b,
| ^^^^^^ pattern cannot match with input type `Vec<i32>`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0529`.

0 comments on commit a937dd5

Please sign in to comment.