mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-30 16:43:41 +00:00
Rollup merge of #91343 - FabianWolff:issue-91328-as-deref, r=jackh726
Fix suggestion to slice if scrutinee is a `Result` or `Option` Fixes #91328.
This commit is contained in:
commit
5159c013b0
@ -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};
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
37
src/test/ui/typeck/issue-91328.fixed
Normal file
37
src/test/ui/typeck/issue-91328.fixed
Normal file
@ -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
src/test/ui/typeck/issue-91328.rs
Normal file
37
src/test/ui/typeck/issue-91328.rs
Normal file
@ -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
src/test/ui/typeck/issue-91328.stderr
Normal file
30
src/test/ui/typeck/issue-91328.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user