Skip to content

Commit 036d200

Browse files
authored
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
2 parents 3518844 + efe438b commit 036d200

File tree

3 files changed

+96
-49
lines changed

3 files changed

+96
-49
lines changed

compiler/rustc_typeck/src/check/pat.rs

+46-49
Original file line numberDiff line numberDiff line change
@@ -2042,63 +2042,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20422042
self.tcx.sess,
20432043
span,
20442044
E0529,
2045-
"expected an array or slice, found `{}`",
2046-
expected_ty
2045+
"expected an array or slice, found `{expected_ty}`"
20472046
);
2048-
if let ty::Ref(_, ty, _) = expected_ty.kind() {
2049-
if let ty::Array(..) | ty::Slice(..) = ty.kind() {
2050-
err.help("the semantics of slice patterns changed recently; see issue #62254");
2051-
}
2047+
if let ty::Ref(_, ty, _) = expected_ty.kind()
2048+
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
2049+
{
2050+
err.help("the semantics of slice patterns changed recently; see issue #62254");
20522051
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
20532052
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
2053+
&& let (Some(span), true) = (ti.span, ti.origin_expr)
2054+
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
20542055
{
2055-
if let (Some(span), true) = (ti.span, ti.origin_expr) {
2056-
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
2057-
let applicability = Autoderef::new(
2058-
&self.infcx,
2059-
self.param_env,
2060-
self.body_id,
2061-
span,
2062-
self.resolve_vars_if_possible(ti.expected),
2056+
let ty = self.resolve_vars_if_possible(ti.expected);
2057+
let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty);
2058+
match is_slice_or_array_or_vector.1.kind() {
2059+
ty::Adt(adt_def, _)
2060+
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
2061+
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
2062+
{
2063+
// Slicing won't work here, but `.as_deref()` might (issue #91328).
2064+
err.span_suggestion(
20632065
span,
2064-
)
2065-
.find_map(|(ty, _)| {
2066-
match ty.kind() {
2067-
ty::Adt(adt_def, _)
2068-
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
2069-
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
2070-
{
2071-
// Slicing won't work here, but `.as_deref()` might (issue #91328).
2072-
err.span_suggestion(
2073-
span,
2074-
"consider using `as_deref` here",
2075-
format!("{}.as_deref()", snippet),
2076-
Applicability::MaybeIncorrect,
2077-
);
2078-
Some(None)
2079-
}
2080-
2081-
ty::Slice(..) | ty::Array(..) => {
2082-
Some(Some(Applicability::MachineApplicable))
2083-
}
2084-
2085-
_ => None,
2086-
}
2087-
})
2088-
.unwrap_or(Some(Applicability::MaybeIncorrect));
2089-
2090-
if let Some(applicability) = applicability {
2091-
err.span_suggestion(
2092-
span,
2093-
"consider slicing here",
2094-
format!("{}[..]", snippet),
2095-
applicability,
2096-
);
2097-
}
2066+
"consider using `as_deref` here",
2067+
format!("{snippet}.as_deref()"),
2068+
Applicability::MaybeIncorrect,
2069+
);
20982070
}
2071+
_ => ()
2072+
}
2073+
if is_slice_or_array_or_vector.0 {
2074+
err.span_suggestion(
2075+
span,
2076+
"consider slicing here",
2077+
format!("{snippet}[..]"),
2078+
Applicability::MachineApplicable,
2079+
);
20992080
}
21002081
}
2101-
err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty));
2082+
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
21022083
err.emit();
21032084
}
2085+
2086+
fn is_slice_or_array_or_vector(
2087+
&self,
2088+
err: &mut Diagnostic,
2089+
snippet: String,
2090+
ty: Ty<'tcx>,
2091+
) -> (bool, Ty<'tcx>) {
2092+
match ty.kind() {
2093+
ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
2094+
(true, ty)
2095+
}
2096+
ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty),
2097+
ty::Slice(..) | ty::Array(..) => (true, ty),
2098+
_ => (false, ty),
2099+
}
2100+
}
21042101
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use std::ops::Deref;
2+
3+
struct Foo {
4+
v: Vec<u32>,
5+
}
6+
7+
struct Bar {
8+
v: Vec<u32>,
9+
}
10+
11+
impl Deref for Bar {
12+
type Target = Vec<u32>;
13+
14+
fn deref(&self) -> &Self::Target {
15+
&self.v
16+
}
17+
}
18+
19+
fn f(foo: &Foo) {
20+
match foo {
21+
Foo { v: [1, 2] } => {}
22+
//~^ ERROR expected an array or slice, found `Vec<u32>
23+
_ => {}
24+
}
25+
}
26+
27+
fn bar(bar: &Bar) {
28+
match bar {
29+
Bar { v: [1, 2] } => {}
30+
//~^ ERROR expected an array or slice, found `Vec<u32>
31+
_ => {}
32+
}
33+
}
34+
35+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0529]: expected an array or slice, found `Vec<u32>`
2+
--> $DIR/pattern-struct-with-slice-vec-field.rs:21:18
3+
|
4+
LL | Foo { v: [1, 2] } => {}
5+
| ^^^^^^ pattern cannot match with input type `Vec<u32>`
6+
7+
error[E0529]: expected an array or slice, found `Vec<u32>`
8+
--> $DIR/pattern-struct-with-slice-vec-field.rs:29:18
9+
|
10+
LL | Bar { v: [1, 2] } => {}
11+
| ^^^^^^ pattern cannot match with input type `Vec<u32>`
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0529`.

0 commit comments

Comments
 (0)