Skip to content

Commit

Permalink
Don't show suggestion if slice pattern is enclosed by struct
Browse files Browse the repository at this point in the history
  • Loading branch information
long-long-float committed Feb 27, 2024
1 parent 9afdb8d commit 9e5ade0
Showing 1 changed file with 48 additions and 13 deletions.
61 changes: 48 additions & 13 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ struct PatInfo<'tcx, 'a> {
binding_mode: BindingMode,
top_info: TopInfo<'tcx>,
decl_origin: Option<DeclOrigin<'a>>,

parent_kind: Option<PatKind<'tcx>>,
current_kind: Option<PatKind<'tcx>>,
}

impl<'tcx> FnCtxt<'_, 'tcx> {
Expand Down Expand Up @@ -153,7 +156,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
decl_origin: Option<DeclOrigin<'tcx>>,
) {
let info = TopInfo { expected, origin_expr, span };
let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin };
let pat_info = PatInfo {
binding_mode: INITIAL_BM,
top_info: info,
decl_origin,
parent_kind: None,
current_kind: None,
};
self.check_pat(pat, expected, pat_info);
}

Expand All @@ -164,7 +173,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Conversely, inside this module, `check_pat_top` should never be used.
#[instrument(level = "debug", skip(self, pat_info))]
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
let PatInfo { binding_mode: def_bm, top_info: ti, current_kind, .. } = pat_info;

let path_res = match &pat.kind {
PatKind::Path(qpath) => Some(
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
Expand All @@ -173,8 +183,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
let pat_info =
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin };
let pat_info = PatInfo {
binding_mode: def_bm,
top_info: ti,
decl_origin: pat_info.decl_origin,
parent_kind: current_kind,
current_kind: Some(pat.kind),
};

let ty = match pat.kind {
PatKind::Wild | PatKind::Err(_) => expected,
Expand Down Expand Up @@ -1047,14 +1062,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx, '_>,
) -> Ty<'tcx> {
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, parent_kind, current_kind } =
pat_info;
let tcx = self.tcx;
let on_error = |e| {
for pat in subpats {
self.check_pat(
pat,
Ty::new_error(tcx, e),
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
PatInfo {
binding_mode: def_bm,
top_info: ti,
decl_origin,
parent_kind,
current_kind,
},
);
}
};
Expand Down Expand Up @@ -1121,7 +1143,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_pat(
subpat,
field_ty,
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
PatInfo {
binding_mode: def_bm,
top_info: ti,
decl_origin,
parent_kind,
current_kind,
},
);

self.tcx.check_stability(
Expand Down Expand Up @@ -2135,7 +2163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// The expected type must be an array or slice, but was neither, so error.
_ => {
let guar = expected.error_reported().err().unwrap_or_else(|| {
self.error_expected_array_or_slice(span, expected, pat_info.top_info)
self.error_expected_array_or_slice(span, expected, pat_info)
});
let err = Ty::new_error(self.tcx, guar);
(err, Some(err), err)
Expand Down Expand Up @@ -2274,8 +2302,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
span: Span,
expected_ty: Ty<'tcx>,
ti: TopInfo<'tcx>,
pat_info: PatInfo<'tcx, '_>,
) -> ErrorGuaranteed {
let PatInfo { top_info: ti, parent_kind, .. } = pat_info;

let mut err = struct_span_code_err!(
self.dcx(),
span,
Expand All @@ -2293,9 +2323,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(_) = ti.origin_expr
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{
let ty = self.resolve_vars_if_possible(ti.expected);
let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(ty);
match is_slice_or_array_or_vector.1.kind() {
let resolved_ty = self.resolve_vars_if_possible(ti.expected);
let (is_slice_or_array_or_vector, resolved_ty) =
self.is_slice_or_array_or_vector(resolved_ty);
match resolved_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()) =>
Expand All @@ -2310,7 +2341,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => (),
}
if is_slice_or_array_or_vector.0 {

let enclosure_is_struct =
parent_kind.map_or(false, |enclosure| matches!(enclosure, PatKind::Struct(..)));

if is_slice_or_array_or_vector && !enclosure_is_struct {
err.span_suggestion(
span,
"consider slicing here",
Expand Down

0 comments on commit 9e5ade0

Please sign in to comment.