Skip to content

Commit e93728a

Browse files
committed
refactor tuple struct pattern checking to get info for peeling
See the previous two commits. This one required the most restructuring/indentation.
1 parent 0a0a8b7 commit e93728a

File tree

2 files changed

+91
-79
lines changed

2 files changed

+91
-79
lines changed

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![feature(let_chains)]
1010
#![feature(never_type)]
1111
#![feature(try_blocks)]
12+
#![feature(yeet_expr)]
1213
// tidy-alphabetical-end
1314

1415
mod _match;

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 90 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
364364
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
365365
Some { 0: &self.check_pat_struct(pat, qpath, fields, has_rest_pat) }
366366
}
367+
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
368+
Some { 0: &self.check_pat_tuple_struct(pat, qpath, subpats, ddpos) }
369+
}
367370
_ => None,
368371
};
369372
let adjust_mode = self.calc_adjust_mode(pat, resolved_pat.and_then(|r| r.path_res));
@@ -393,9 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
393396
PatKind::Binding(ba, var_id, ident, sub) => {
394397
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
395398
}
396-
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
397-
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
398-
}
399+
PatKind::TupleStruct(..) => (resolved_pat.unwrap().check)(expected, pat_info),
399400
PatKind::Struct(..) => (resolved_pat.unwrap().check)(expected, pat_info),
400401
PatKind::Guard(pat, cond) => {
401402
self.check_pat(pat, expected, pat_info);
@@ -1446,97 +1447,107 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14461447
qpath: &'tcx hir::QPath<'tcx>,
14471448
subpats: &'tcx [Pat<'tcx>],
14481449
ddpos: hir::DotDotPos,
1449-
expected: Ty<'tcx>,
1450-
pat_info: PatInfo<'tcx>,
1451-
) -> Ty<'tcx> {
1450+
) -> ResolvedPat<impl Fn(Ty<'tcx>, PatInfo<'tcx>) -> Ty<'tcx>> {
14521451
let tcx = self.tcx;
1453-
let on_error = |e| {
1454-
for pat in subpats {
1455-
self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
1456-
}
1457-
};
14581452
let report_unexpected_res = |res: Res| {
14591453
let expected = "tuple struct or tuple variant";
1460-
let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
1461-
on_error(e);
1462-
e
1454+
report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected)
14631455
};
14641456

1465-
// Resolve the path and check the definition for errors.
1466-
let (res, opt_ty, segments) =
1467-
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
1468-
if res == Res::Err {
1469-
let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
1470-
self.set_tainted_by_errors(e);
1471-
on_error(e);
1472-
return Ty::new_error(tcx, e);
1473-
}
1474-
1475-
// Type-check the path.
1476-
let (pat_ty, res) =
1477-
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
1478-
if !pat_ty.is_fn() {
1479-
let e = report_unexpected_res(res);
1480-
return Ty::new_error(tcx, e);
1481-
}
1482-
1483-
let variant = match res {
1484-
Res::Err => {
1485-
self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
1457+
let pat_ty_and_res_and_variant = try {
1458+
// Resolve the path and check the definition for errors.
1459+
let (res, opt_ty, segments) =
1460+
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
1461+
if res == Res::Err {
1462+
let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
1463+
self.set_tainted_by_errors(e);
1464+
do yeet e;
14861465
}
1487-
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
1488-
let e = report_unexpected_res(res);
1489-
return Ty::new_error(tcx, e);
1466+
1467+
// Type-check the path.
1468+
let (pat_ty, res) =
1469+
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
1470+
if !pat_ty.is_fn() {
1471+
do yeet report_unexpected_res(res);
14901472
}
1491-
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
1492-
_ => bug!("unexpected pattern resolution: {:?}", res),
1493-
};
14941473

1495-
// Replace constructor type with constructed type for tuple struct patterns.
1496-
let pat_ty = pat_ty.fn_sig(tcx).output();
1497-
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1474+
let variant = match res {
1475+
Res::Err => {
1476+
self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
1477+
}
1478+
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
1479+
do yeet report_unexpected_res(res);
1480+
}
1481+
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
1482+
_ => bug!("unexpected pattern resolution: {:?}", res),
1483+
};
14981484

1499-
// Type-check the tuple struct pattern against the expected type.
1500-
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
1501-
let had_err = diag.map_err(|diag| diag.emit());
1485+
// Replace constructor type with constructed type for tuple struct patterns.
1486+
let pat_ty = pat_ty.fn_sig(tcx).output();
1487+
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
15021488

1503-
// Type-check subpatterns.
1504-
if subpats.len() == variant.fields.len()
1505-
|| subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
1506-
{
1507-
let ty::Adt(_, args) = pat_ty.kind() else {
1508-
bug!("unexpected pattern type {:?}", pat_ty);
1489+
(pat_ty, res, variant)
1490+
};
1491+
1492+
let check = move |expected: Ty<'tcx>, pat_info: PatInfo<'tcx>| -> Ty<'tcx> {
1493+
let on_error = |e| {
1494+
for pat in subpats {
1495+
self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
1496+
}
15091497
};
1510-
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1511-
let field = &variant.fields[FieldIdx::from_usize(i)];
1512-
let field_ty = self.field_ty(subpat.span, field, args);
1513-
self.check_pat(subpat, field_ty, pat_info);
1514-
1515-
self.tcx.check_stability(
1516-
variant.fields[FieldIdx::from_usize(i)].did,
1517-
Some(subpat.hir_id),
1518-
subpat.span,
1519-
None,
1498+
let (pat_ty, res, variant) = match pat_ty_and_res_and_variant {
1499+
Ok(data) => data,
1500+
Err(guar) => {
1501+
on_error(guar);
1502+
return Ty::new_error(tcx, guar);
1503+
}
1504+
};
1505+
1506+
// Type-check the tuple struct pattern against the expected type.
1507+
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
1508+
let had_err = diag.map_err(|diag| diag.emit());
1509+
1510+
// Type-check subpatterns.
1511+
if subpats.len() == variant.fields.len()
1512+
|| subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
1513+
{
1514+
let ty::Adt(_, args) = pat_ty.kind() else {
1515+
bug!("unexpected pattern type {:?}", pat_ty);
1516+
};
1517+
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos)
1518+
{
1519+
let field = &variant.fields[FieldIdx::from_usize(i)];
1520+
let field_ty = self.field_ty(subpat.span, field, args);
1521+
self.check_pat(subpat, field_ty, pat_info);
1522+
1523+
self.tcx.check_stability(
1524+
variant.fields[FieldIdx::from_usize(i)].did,
1525+
Some(subpat.hir_id),
1526+
subpat.span,
1527+
None,
1528+
);
1529+
}
1530+
if let Err(e) = had_err {
1531+
on_error(e);
1532+
return Ty::new_error(tcx, e);
1533+
}
1534+
} else {
1535+
let e = self.emit_err_pat_wrong_number_of_fields(
1536+
pat.span,
1537+
res,
1538+
qpath,
1539+
subpats,
1540+
&variant.fields.raw,
1541+
expected,
1542+
had_err,
15201543
);
1521-
}
1522-
if let Err(e) = had_err {
15231544
on_error(e);
15241545
return Ty::new_error(tcx, e);
15251546
}
1526-
} else {
1527-
let e = self.emit_err_pat_wrong_number_of_fields(
1528-
pat.span,
1529-
res,
1530-
qpath,
1531-
subpats,
1532-
&variant.fields.raw,
1533-
expected,
1534-
had_err,
1535-
);
1536-
on_error(e);
1537-
return Ty::new_error(tcx, e);
1538-
}
1539-
pat_ty
1547+
pat_ty
1548+
};
1549+
1550+
ResolvedPat { path_res: None, check }
15401551
}
15411552

15421553
fn emit_err_pat_wrong_number_of_fields(

0 commit comments

Comments
 (0)