Skip to content

Commit c15ef58

Browse files
committed
Fix suggestion to slice if scrutinee is a Result or Option
1 parent 24b8bb1 commit c15ef58

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

compiler/rustc_typeck/src/check/pat.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
1515
use rustc_span::hygiene::DesugaringKind;
1616
use rustc_span::lev_distance::find_best_match_for_name;
1717
use rustc_span::source_map::{Span, Spanned};
18-
use rustc_span::symbol::Ident;
18+
use rustc_span::symbol::{sym, Ident};
1919
use rustc_span::{BytePos, MultiSpan, DUMMY_SP};
2020
use rustc_trait_selection::autoderef::Autoderef;
2121
use rustc_trait_selection::traits::{ObligationCause, Pattern};
@@ -2033,12 +2033,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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-
err.span_suggestion(
2037-
span,
2038-
"consider slicing here",
2039-
format!("{}[..]", snippet),
2040-
Applicability::MachineApplicable,
2041-
);
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+
ty::Adt(adt_def, _)
2051+
if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) =>
2052+
{
2053+
Some(Applicability::MachineApplicable)
2054+
}
2055+
_ => Some(Applicability::MaybeIncorrect),
2056+
};
2057+
2058+
if let Some(applicability) = applicability {
2059+
err.span_suggestion(
2060+
span,
2061+
"consider slicing here",
2062+
format!("{}[..]", snippet),
2063+
applicability,
2064+
);
2065+
}
20422066
}
20432067
}
20442068
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Regression test for issue #91328.
2+
3+
// run-rustfix
4+
5+
#![allow(dead_code)]
6+
7+
fn foo(r: Result<Vec<i32>, i32>) -> i32 {
8+
match r.as_deref() {
9+
//~^ HELP: consider using `as_deref` here
10+
Ok([a, b]) => a + b,
11+
//~^ ERROR: expected an array or slice
12+
//~| NOTE: pattern cannot match with input type
13+
_ => 42,
14+
}
15+
}
16+
17+
fn bar(o: Option<Vec<i32>>) -> i32 {
18+
match o.as_deref() {
19+
//~^ HELP: consider using `as_deref` here
20+
Some([a, b]) => a + b,
21+
//~^ ERROR: expected an array or slice
22+
//~| NOTE: pattern cannot match with input type
23+
_ => 42,
24+
}
25+
}
26+
27+
fn main() {}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Regression test for issue #91328.
2+
3+
// run-rustfix
4+
5+
#![allow(dead_code)]
6+
7+
fn foo(r: Result<Vec<i32>, i32>) -> i32 {
8+
match r {
9+
//~^ HELP: consider using `as_deref` here
10+
Ok([a, b]) => a + b,
11+
//~^ ERROR: expected an array or slice
12+
//~| NOTE: pattern cannot match with input type
13+
_ => 42,
14+
}
15+
}
16+
17+
fn bar(o: Option<Vec<i32>>) -> i32 {
18+
match o {
19+
//~^ HELP: consider using `as_deref` here
20+
Some([a, b]) => a + b,
21+
//~^ ERROR: expected an array or slice
22+
//~| NOTE: pattern cannot match with input type
23+
_ => 42,
24+
}
25+
}
26+
27+
fn main() {}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0529]: expected an array or slice, found `Vec<i32>`
2+
--> $DIR/issue-91328.rs:10:12
3+
|
4+
LL | match r {
5+
| - help: consider using `as_deref` here: `r.as_deref()`
6+
LL |
7+
LL | Ok([a, b]) => a + b,
8+
| ^^^^^^ pattern cannot match with input type `Vec<i32>`
9+
10+
error[E0529]: expected an array or slice, found `Vec<i32>`
11+
--> $DIR/issue-91328.rs:20:14
12+
|
13+
LL | match o {
14+
| - help: consider using `as_deref` here: `o.as_deref()`
15+
LL |
16+
LL | Some([a, b]) => a + b,
17+
| ^^^^^^ pattern cannot match with input type `Vec<i32>`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0529`.

0 commit comments

Comments
 (0)