Skip to content

Commit 323ff3d

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 0131586 commit 323ff3d

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);
@@ -1451,97 +1452,107 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14511452
qpath: &'tcx hir::QPath<'tcx>,
14521453
subpats: &'tcx [Pat<'tcx>],
14531454
ddpos: hir::DotDotPos,
1454-
expected: Ty<'tcx>,
1455-
pat_info: PatInfo<'tcx>,
1456-
) -> Ty<'tcx> {
1455+
) -> ResolvedPat<impl Fn(Ty<'tcx>, PatInfo<'tcx>) -> Ty<'tcx>> {
14571456
let tcx = self.tcx;
1458-
let on_error = |e| {
1459-
for pat in subpats {
1460-
self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
1461-
}
1462-
};
14631457
let report_unexpected_res = |res: Res| {
14641458
let expected = "tuple struct or tuple variant";
1465-
let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
1466-
on_error(e);
1467-
e
1459+
report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected)
14681460
};
14691461

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

1500-
// Replace constructor type with constructed type for tuple struct patterns.
1501-
let pat_ty = pat_ty.fn_sig(tcx).output();
1502-
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1479+
let variant = match res {
1480+
Res::Err => {
1481+
self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
1482+
}
1483+
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
1484+
do yeet report_unexpected_res(res);
1485+
}
1486+
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
1487+
_ => bug!("unexpected pattern resolution: {:?}", res),
1488+
};
15031489

1504-
// Type-check the tuple struct pattern against the expected type.
1505-
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
1506-
let had_err = diag.map_err(|diag| diag.emit());
1490+
// Replace constructor type with constructed type for tuple struct patterns.
1491+
let pat_ty = pat_ty.fn_sig(tcx).output();
1492+
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
15071493

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

15471558
fn emit_err_pat_wrong_number_of_fields(

0 commit comments

Comments
 (0)