@@ -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 ( pat. 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 ( pat. 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