mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 07:03:45 +00:00
Rollup merge of #96122 - TaKO8Ki:fix-invalid-error-for-suggestion-to-add-slice-in-pattern-matching, r=nagisa
Fix an invalid error for a suggestion to add a slice in pattern-matching closes #96103
This commit is contained in:
commit
036d200d1c
@ -2042,63 +2042,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0529,
|
||||
"expected an array or slice, found `{}`",
|
||||
expected_ty
|
||||
"expected an array or slice, found `{expected_ty}`"
|
||||
);
|
||||
if let ty::Ref(_, ty, _) = expected_ty.kind() {
|
||||
if let ty::Array(..) | ty::Slice(..) = ty.kind() {
|
||||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
||||
}
|
||||
if let ty::Ref(_, ty, _) = expected_ty.kind()
|
||||
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
|
||||
{
|
||||
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(..) | ty::Array(..)))
|
||||
&& let (Some(span), true) = (ti.span, ti.origin_expr)
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
{
|
||||
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 = Autoderef::new(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
self.body_id,
|
||||
let ty = self.resolve_vars_if_possible(ti.expected);
|
||||
let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty);
|
||||
match is_slice_or_array_or_vector.1.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,
|
||||
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,
|
||||
}
|
||||
})
|
||||
.unwrap_or(Some(Applicability::MaybeIncorrect));
|
||||
|
||||
if let Some(applicability) = applicability {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider slicing here",
|
||||
format!("{}[..]", snippet),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
"consider using `as_deref` here",
|
||||
format!("{snippet}.as_deref()"),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
if is_slice_or_array_or_vector.0 {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider slicing here",
|
||||
format!("{snippet}[..]"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty));
|
||||
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn is_slice_or_array_or_vector(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
snippet: String,
|
||||
ty: Ty<'tcx>,
|
||||
) -> (bool, Ty<'tcx>) {
|
||||
match ty.kind() {
|
||||
ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
|
||||
(true, ty)
|
||||
}
|
||||
ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty),
|
||||
ty::Slice(..) | ty::Array(..) => (true, ty),
|
||||
_ => (false, ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
struct Foo {
|
||||
v: Vec<u32>,
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
v: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Deref for Bar {
|
||||
type Target = Vec<u32>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.v
|
||||
}
|
||||
}
|
||||
|
||||
fn f(foo: &Foo) {
|
||||
match foo {
|
||||
Foo { v: [1, 2] } => {}
|
||||
//~^ ERROR expected an array or slice, found `Vec<u32>
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn bar(bar: &Bar) {
|
||||
match bar {
|
||||
Bar { v: [1, 2] } => {}
|
||||
//~^ ERROR expected an array or slice, found `Vec<u32>
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,15 @@
|
||||
error[E0529]: expected an array or slice, found `Vec<u32>`
|
||||
--> $DIR/pattern-struct-with-slice-vec-field.rs:21:18
|
||||
|
|
||||
LL | Foo { v: [1, 2] } => {}
|
||||
| ^^^^^^ pattern cannot match with input type `Vec<u32>`
|
||||
|
||||
error[E0529]: expected an array or slice, found `Vec<u32>`
|
||||
--> $DIR/pattern-struct-with-slice-vec-field.rs:29:18
|
||||
|
|
||||
LL | Bar { v: [1, 2] } => {}
|
||||
| ^^^^^^ pattern cannot match with input type `Vec<u32>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0529`.
|
Loading…
Reference in New Issue
Block a user