Skip to content

Commit 3f0bf55

Browse files
Don't show suggestion if slice pattern is enclosed by struct
1 parent bb8b11e commit 3f0bf55

File tree

1 file changed

+47
-22
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+47
-22
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+47-22
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,12 @@ struct TopInfo<'tcx> {
7979
span: Option<Span>,
8080
}
8181

82-
#[derive(Copy, Clone)]
82+
#[derive(Clone)]
8383
struct PatInfo<'tcx, 'a> {
8484
binding_mode: BindingMode,
8585
top_info: TopInfo<'tcx>,
8686
decl_origin: Option<DeclOrigin<'a>>,
87+
history: Vec<PatKind<'tcx>>,
8788
}
8889

8990
impl<'tcx> FnCtxt<'_, 'tcx> {
@@ -153,7 +154,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
153154
decl_origin: Option<DeclOrigin<'tcx>>,
154155
) {
155156
let info = TopInfo { expected, origin_expr, span };
156-
let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin };
157+
let pat_info =
158+
PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin, history: Vec::new() };
157159
self.check_pat(pat, expected, pat_info);
158160
}
159161

@@ -164,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
164166
/// Conversely, inside this module, `check_pat_top` should never be used.
165167
#[instrument(level = "debug", skip(self, pat_info))]
166168
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
167-
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
169+
let PatInfo { binding_mode: def_bm, top_info: ti, mut history, .. } = pat_info;
168170
let path_res = match &pat.kind {
169171
PatKind::Path(qpath) => Some(
170172
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
@@ -173,8 +175,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173175
};
174176
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
175177
let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
176-
let pat_info =
177-
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin };
178+
history.push(pat.kind);
179+
let pat_info = PatInfo {
180+
binding_mode: def_bm,
181+
top_info: ti,
182+
decl_origin: pat_info.decl_origin,
183+
history,
184+
};
178185

179186
let ty = match pat.kind {
180187
PatKind::Wild | PatKind::Err(_) => expected,
@@ -196,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
196203
}
197204
PatKind::Or(pats) => {
198205
for pat in pats {
199-
self.check_pat(pat, expected, pat_info);
206+
self.check_pat(pat, expected, pat_info.clone());
200207
}
201208
expected
202209
}
@@ -869,7 +876,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
869876
Err(guar) => {
870877
let err = Ty::new_error(self.tcx, guar);
871878
for field in fields {
872-
self.check_pat(field.pat, err, pat_info);
879+
self.check_pat(field.pat, err, pat_info.clone());
873880
}
874881
return err;
875882
}
@@ -1047,14 +1054,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10471054
expected: Ty<'tcx>,
10481055
pat_info: PatInfo<'tcx, '_>,
10491056
) -> Ty<'tcx> {
1050-
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
1057+
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, history } = pat_info;
10511058
let tcx = self.tcx;
10521059
let on_error = |e| {
10531060
for pat in subpats {
10541061
self.check_pat(
10551062
pat,
10561063
Ty::new_error(tcx, e),
1057-
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
1064+
PatInfo {
1065+
binding_mode: def_bm,
1066+
top_info: ti,
1067+
decl_origin,
1068+
history: history.clone(),
1069+
},
10581070
);
10591071
}
10601072
};
@@ -1124,7 +1136,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11241136
self.check_pat(
11251137
subpat,
11261138
field_ty,
1127-
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
1139+
PatInfo {
1140+
binding_mode: def_bm,
1141+
top_info: ti,
1142+
decl_origin,
1143+
history: history.clone(),
1144+
},
11281145
);
11291146

11301147
self.tcx.check_stability(
@@ -1336,12 +1353,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13361353
// further errors being emitted when using the bindings. #50333
13371354
let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
13381355
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1339-
self.check_pat(elem, Ty::new_error(tcx, reported), pat_info);
1356+
self.check_pat(elem, Ty::new_error(tcx, reported), pat_info.clone());
13401357
}
13411358
Ty::new_tup_from_iter(tcx, element_tys_iter)
13421359
} else {
13431360
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1344-
self.check_pat(elem, element_tys[i], pat_info);
1361+
self.check_pat(elem, element_tys[i], pat_info.clone());
13451362
}
13461363
pat_ty
13471364
}
@@ -1402,7 +1419,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14021419
}
14031420
};
14041421

1405-
self.check_pat(field.pat, field_ty, pat_info);
1422+
self.check_pat(field.pat, field_ty, pat_info.clone());
14061423
}
14071424

14081425
let mut unmentioned_fields = variant
@@ -2138,7 +2155,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21382155
// The expected type must be an array or slice, but was neither, so error.
21392156
_ => {
21402157
let guar = expected.error_reported().err().unwrap_or_else(|| {
2141-
self.error_expected_array_or_slice(span, expected, pat_info.top_info)
2158+
self.error_expected_array_or_slice(span, expected, pat_info.clone())
21422159
});
21432160
let err = Ty::new_error(self.tcx, guar);
21442161
(err, Some(err), err)
@@ -2147,15 +2164,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21472164

21482165
// Type check all the patterns before `slice`.
21492166
for elt in before {
2150-
self.check_pat(elt, element_ty, pat_info);
2167+
self.check_pat(elt, element_ty, pat_info.clone());
21512168
}
21522169
// Type check the `slice`, if present, against its expected type.
21532170
if let Some(slice) = slice {
2154-
self.check_pat(slice, opt_slice_ty.unwrap(), pat_info);
2171+
self.check_pat(slice, opt_slice_ty.unwrap(), pat_info.clone());
21552172
}
21562173
// Type check the elements after `slice`, if present.
21572174
for elt in after {
2158-
self.check_pat(elt, element_ty, pat_info);
2175+
self.check_pat(elt, element_ty, pat_info.clone());
21592176
}
21602177
inferred
21612178
}
@@ -2277,8 +2294,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22772294
&self,
22782295
span: Span,
22792296
expected_ty: Ty<'tcx>,
2280-
ti: TopInfo<'tcx>,
2297+
pat_info: PatInfo<'tcx, '_>,
22812298
) -> ErrorGuaranteed {
2299+
let PatInfo { top_info: ti, history, .. } = pat_info;
2300+
22822301
let mut err = struct_span_code_err!(
22832302
self.dcx(),
22842303
span,
@@ -2296,9 +2315,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22962315
&& let Some(_) = ti.origin_expr
22972316
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
22982317
{
2299-
let ty = self.resolve_vars_if_possible(ti.expected);
2300-
let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(ty);
2301-
match is_slice_or_array_or_vector.1.kind() {
2318+
let resolved_ty = self.resolve_vars_if_possible(ti.expected);
2319+
let (is_slice_or_array_or_vector, resolved_ty) =
2320+
self.is_slice_or_array_or_vector(resolved_ty);
2321+
match resolved_ty.kind() {
23022322
ty::Adt(adt_def, _)
23032323
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
23042324
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
@@ -2313,7 +2333,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23132333
}
23142334
_ => (),
23152335
}
2316-
if is_slice_or_array_or_vector.0 {
2336+
2337+
let enclosure_is_struct = history
2338+
.get(history.len() - 2)
2339+
.map_or(false, |enclosure| matches!(enclosure, PatKind::Struct(..)));
2340+
2341+
if is_slice_or_array_or_vector && !enclosure_is_struct {
23172342
err.span_suggestion(
23182343
span,
23192344
"consider slicing here",

0 commit comments

Comments
 (0)