Skip to content

Commit 9601326

Browse files
committed
refactor struct pattern checking to get info for peeling
See the previous commit for details. This doesn't yet extract the struct pat's type's ADT def before peeling, but it should now be possible.
1 parent f257854 commit 9601326

File tree

1 file changed

+32
-19
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+32
-19
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -277,12 +277,14 @@ struct ResolvedPat<'tcx> {
277277
#[derive(Clone, Copy, Debug)]
278278
enum ResolvedPatKind<'tcx> {
279279
Path { res: Res, pat_res: Res, segments: &'tcx [hir::PathSegment<'tcx>] },
280+
Struct { variant: &'tcx VariantDef },
280281
}
281282

282283
impl<'tcx> ResolvedPat<'tcx> {
283284
fn adjust_mode(&self) -> AdjustMode {
284-
let ResolvedPatKind::Path { res, .. } = self.kind;
285-
if matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _)) {
285+
if let ResolvedPatKind::Path { res, .. } = self.kind
286+
&& matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _))
287+
{
286288
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
287289
// Peeling the reference types too early will cause type checking failures.
288290
// Although it would be possible to *also* peel the types of the constants too.
@@ -380,6 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
380382
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
381383
Some(self.resolve_pat_path(*hir_id, *span, qpath))
382384
}
385+
PatKind::Struct(ref qpath, ..) => Some(self.resolve_pat_struct(pat, qpath)),
383386
_ => None,
384387
};
385388
let opt_res_pat = opt_res_pat_or_err.map(Result::ok).flatten();
@@ -419,9 +422,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
419422
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
420423
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
421424
}
422-
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
423-
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
424-
}
425+
PatKind::Struct(_, fields, has_rest_pat) => match opt_res_pat_or_err.unwrap() {
426+
Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self
427+
.check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info),
428+
Err(guar) => {
429+
let ty_err = Ty::new_error(self.tcx, guar);
430+
for field in fields {
431+
self.check_pat(field.pat, ty_err, pat_info);
432+
}
433+
ty_err
434+
}
435+
Ok(r) => span_bug!(pat.span, "struct pattern resolved to {r:?}"),
436+
},
425437
PatKind::Guard(pat, cond) => {
426438
self.check_pat(pat, expected, pat_info);
427439
self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
@@ -1246,27 +1258,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12461258
Ok(())
12471259
}
12481260

1249-
fn check_pat_struct(
1261+
fn resolve_pat_struct(
12501262
&self,
12511263
pat: &'tcx Pat<'tcx>,
12521264
qpath: &hir::QPath<'tcx>,
1265+
) -> Result<ResolvedPat<'tcx>, ErrorGuaranteed> {
1266+
// Resolve the path and check the definition for errors.
1267+
let (variant, pat_ty) = self.check_struct_path(qpath, pat.hir_id)?;
1268+
Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::Struct { variant } })
1269+
}
1270+
1271+
fn check_pat_struct(
1272+
&self,
1273+
pat: &'tcx Pat<'tcx>,
12531274
fields: &'tcx [hir::PatField<'tcx>],
12541275
has_rest_pat: bool,
1276+
pat_ty: Ty<'tcx>,
1277+
variant: &'tcx VariantDef,
12551278
expected: Ty<'tcx>,
12561279
pat_info: PatInfo<'tcx>,
12571280
) -> Ty<'tcx> {
1258-
// Resolve the path and check the definition for errors.
1259-
let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
1260-
Ok(data) => data,
1261-
Err(guar) => {
1262-
let err = Ty::new_error(self.tcx, guar);
1263-
for field in fields {
1264-
self.check_pat(field.pat, err, pat_info);
1265-
}
1266-
return err;
1267-
}
1268-
};
1269-
12701281
// Type-check the path.
12711282
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
12721283

@@ -1392,7 +1403,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13921403
pat_span: Span,
13931404
resolved_pat: &ResolvedPat<'tcx>,
13941405
) {
1395-
let ResolvedPatKind::Path { res, pat_res, segments } = resolved_pat.kind;
1406+
let ResolvedPatKind::Path { res, pat_res, segments } = resolved_pat.kind else {
1407+
span_bug!(pat_span, "unexpected resolution for path pattern: {resolved_pat:?}");
1408+
};
13961409

13971410
if let Some(span) = self.tcx.hir_res_span(pat_res) {
13981411
e.span_label(span, format!("{} defined here", res.descr()));

0 commit comments

Comments
 (0)