Skip to content

Commit

Permalink
Rollup merge of rust-lang#93981 - ChayimFriedman2:slice-pat-reference…
Browse files Browse the repository at this point in the history
…-option-result, r=davidtwco

Fix suggestion to slice if scurtinee is a reference to `Result` or `Option`

Fixes rust-lang#91343 (comment) and rust-lang#91343 (comment).
  • Loading branch information
matthiaskrgr authored Feb 16, 2022
2 parents cc7d11e + d9592d9 commit c52e064
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 25 deletions.
56 changes: 32 additions & 24 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2029,34 +2029,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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(..)))
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
{
if let (Some(span), true) = (ti.span, ti.origin_expr) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
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)
let applicability = Autoderef::new(
&self.infcx,
self.param_env,
self.body_id,
span,
self.resolve_vars_if_possible(ti.expected),
span,
)
.find_map(|(ty, _)| {
match ty.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,
);
Some(None)
}

ty::Slice(..) | ty::Array(..) => {
Some(Some(Applicability::MachineApplicable))
}

_ => None,
}
_ => Some(Applicability::MaybeIncorrect),
};
})
.unwrap_or(Some(Applicability::MaybeIncorrect));

if let Some(applicability) = applicability {
err.span_suggestion(
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/typeck/issue-91328.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ fn baz(v: Vec<i32>) -> i32 {
}
}

fn qux(a: &Option<Box<[i32; 2]>>) -> i32 {
match a.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 main() {}
10 changes: 10 additions & 0 deletions src/test/ui/typeck/issue-91328.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ fn baz(v: Vec<i32>) -> i32 {
}
}

fn qux(a: &Option<Box<[i32; 2]>>) -> i32 {
match a {
//~^ 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 main() {}
11 changes: 10 additions & 1 deletion src/test/ui/typeck/issue-91328.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ LL |
LL | [a, b] => a + b,
| ^^^^^^ pattern cannot match with input type `Vec<i32>`

error: aborting due to 3 previous errors
error[E0529]: expected an array or slice, found `Box<[i32; 2]>`
--> $DIR/issue-91328.rs:40:14
|
LL | match a {
| - help: consider using `as_deref` here: `a.as_deref()`
LL |
LL | Some([a, b]) => a + b,
| ^^^^^^ pattern cannot match with input type `Box<[i32; 2]>`

error: aborting due to 4 previous errors

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

0 comments on commit c52e064

Please sign in to comment.