Skip to content

Commit d9592d9

Browse files
Fix suggestion to slice if scurtinee is a reference to Result or Option
1 parent 9a60099 commit d9592d9

File tree

4 files changed

+62
-25
lines changed

4 files changed

+62
-25
lines changed

compiler/rustc_typeck/src/check/pat.rs

+32-24
Original file line numberDiff line numberDiff line change
@@ -2029,34 +2029,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20292029
err.help("the semantics of slice patterns changed recently; see issue #62254");
20302030
}
20312031
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
2032-
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..)))
2032+
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
20332033
{
20342034
if let (Some(span), true) = (ti.span, ti.origin_expr) {
20352035
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
2036-
let applicability = match self.resolve_vars_if_possible(ti.expected).kind() {
2037-
ty::Adt(adt_def, _)
2038-
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
2039-
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
2040-
{
2041-
// Slicing won't work here, but `.as_deref()` might (issue #91328).
2042-
err.span_suggestion(
2043-
span,
2044-
"consider using `as_deref` here",
2045-
format!("{}.as_deref()", snippet),
2046-
Applicability::MaybeIncorrect,
2047-
);
2048-
None
2049-
}
2050-
// FIXME: instead of checking for Vec only, we could check whether the
2051-
// type implements `Deref<Target=X>`; see
2052-
// https://github.com/rust-lang/rust/pull/91343#discussion_r761466979
2053-
ty::Adt(adt_def, _)
2054-
if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) =>
2055-
{
2056-
Some(Applicability::MachineApplicable)
2036+
let applicability = Autoderef::new(
2037+
&self.infcx,
2038+
self.param_env,
2039+
self.body_id,
2040+
span,
2041+
self.resolve_vars_if_possible(ti.expected),
2042+
span,
2043+
)
2044+
.find_map(|(ty, _)| {
2045+
match ty.kind() {
2046+
ty::Adt(adt_def, _)
2047+
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
2048+
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
2049+
{
2050+
// Slicing won't work here, but `.as_deref()` might (issue #91328).
2051+
err.span_suggestion(
2052+
span,
2053+
"consider using `as_deref` here",
2054+
format!("{}.as_deref()", snippet),
2055+
Applicability::MaybeIncorrect,
2056+
);
2057+
Some(None)
2058+
}
2059+
2060+
ty::Slice(..) | ty::Array(..) => {
2061+
Some(Some(Applicability::MachineApplicable))
2062+
}
2063+
2064+
_ => None,
20572065
}
2058-
_ => Some(Applicability::MaybeIncorrect),
2059-
};
2066+
})
2067+
.unwrap_or(Some(Applicability::MaybeIncorrect));
20602068

20612069
if let Some(applicability) = applicability {
20622070
err.span_suggestion(

src/test/ui/typeck/issue-91328.fixed

+10
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,14 @@ fn baz(v: Vec<i32>) -> i32 {
3434
}
3535
}
3636

37+
fn qux(a: &Option<Box<[i32; 2]>>) -> i32 {
38+
match a.as_deref() {
39+
//~^ HELP: consider using `as_deref` here
40+
Some([a, b]) => a + b,
41+
//~^ ERROR: expected an array or slice
42+
//~| NOTE: pattern cannot match with input type
43+
_ => 42,
44+
}
45+
}
46+
3747
fn main() {}

src/test/ui/typeck/issue-91328.rs

+10
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,14 @@ fn baz(v: Vec<i32>) -> i32 {
3434
}
3535
}
3636

37+
fn qux(a: &Option<Box<[i32; 2]>>) -> i32 {
38+
match a {
39+
//~^ HELP: consider using `as_deref` here
40+
Some([a, b]) => a + b,
41+
//~^ ERROR: expected an array or slice
42+
//~| NOTE: pattern cannot match with input type
43+
_ => 42,
44+
}
45+
}
46+
3747
fn main() {}

src/test/ui/typeck/issue-91328.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ LL |
2525
LL | [a, b] => a + b,
2626
| ^^^^^^ pattern cannot match with input type `Vec<i32>`
2727

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

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

0 commit comments

Comments
 (0)