Rollup merge of #93981 - ChayimFriedman2:slice-pat-reference-option-result, r=davidtwco
Fix suggestion to slice if scurtinee is a reference to `Result` or `Option` Fixes https://github.com/rust-lang/rust/pull/91343#issuecomment-1037718339 and https://github.com/rust-lang/rust/pull/91343#discussion_r761466979.
This commit is contained in:
commit
2c0df80a2e
4 changed files with 62 additions and 25 deletions
compiler/rustc_typeck/src/check
src/test/ui/typeck
|
@ -2029,34 +2029,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
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)
|
} 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 (Some(span), true) = (ti.span, ti.origin_expr) {
|
||||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
let applicability = match self.resolve_vars_if_possible(ti.expected).kind() {
|
let applicability = Autoderef::new(
|
||||||
ty::Adt(adt_def, _)
|
&self.infcx,
|
||||||
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
|
self.param_env,
|
||||||
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
|
self.body_id,
|
||||||
{
|
span,
|
||||||
// Slicing won't work here, but `.as_deref()` might (issue #91328).
|
self.resolve_vars_if_possible(ti.expected),
|
||||||
err.span_suggestion(
|
span,
|
||||||
span,
|
)
|
||||||
"consider using `as_deref` here",
|
.find_map(|(ty, _)| {
|
||||||
format!("{}.as_deref()", snippet),
|
match ty.kind() {
|
||||||
Applicability::MaybeIncorrect,
|
ty::Adt(adt_def, _)
|
||||||
);
|
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
|
||||||
None
|
|| 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,
|
||||||
}
|
}
|
||||||
// FIXME: instead of checking for Vec only, we could check whether the
|
})
|
||||||
// type implements `Deref<Target=X>`; see
|
.unwrap_or(Some(Applicability::MaybeIncorrect));
|
||||||
// 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 {
|
if let Some(applicability) = applicability {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
|
|
|
@ -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() {}
|
fn main() {}
|
||||||
|
|
|
@ -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() {}
|
fn main() {}
|
||||||
|
|
|
@ -25,6 +25,15 @@ LL |
|
||||||
LL | [a, b] => a + b,
|
LL | [a, b] => a + b,
|
||||||
| ^^^^^^ pattern cannot match with input type `Vec<i32>`
|
| ^^^^^^ 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`.
|
For more information about this error, try `rustc --explain E0529`.
|
||||||
|
|
Loading…
Add table
Reference in a new issue