@@ -278,6 +278,7 @@ struct ResolvedPat<'tcx> {
278
278
enum ResolvedPatKind < ' tcx > {
279
279
Path { res : Res , pat_res : Res , segments : & ' tcx [ hir:: PathSegment < ' tcx > ] } ,
280
280
Struct { variant : & ' tcx VariantDef } ,
281
+ TupleStruct { res : Res , variant : & ' tcx VariantDef } ,
281
282
}
282
283
283
284
impl < ' tcx > ResolvedPat < ' tcx > {
@@ -381,6 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
381
382
Some ( self . resolve_pat_path ( * hir_id, * span, qpath) )
382
383
}
383
384
PatKind :: Struct ( ref qpath, ..) => Some ( self . resolve_pat_struct ( pat, qpath) ) ,
385
+ PatKind :: TupleStruct ( ref qpath, ..) => Some ( self . resolve_pat_tuple_struct ( pat, qpath) ) ,
384
386
_ => None ,
385
387
} ;
386
388
let adjust_mode = self . calc_adjust_mode ( pat, opt_path_res) ;
@@ -575,9 +577,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
575
577
PatKind :: Binding ( ba, var_id, ident, sub) => {
576
578
self . check_pat_ident ( pat, ba, var_id, ident, sub, expected, pat_info)
577
579
}
578
- PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
579
- self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
580
- }
580
+ PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => match opt_path_res. unwrap ( ) {
581
+ Ok ( ResolvedPat { ty, kind : ResolvedPatKind :: TupleStruct { res, variant } } ) => self
582
+ . check_pat_tuple_struct (
583
+ pat, qpath, subpats, ddpos, res, ty, variant, expected, pat_info,
584
+ ) ,
585
+ Err ( guar) => {
586
+ let ty_err = Ty :: new_error ( self . tcx , guar) ;
587
+ for subpat in subpats {
588
+ self . check_pat ( subpat, ty_err, pat_info) ;
589
+ }
590
+ ty_err
591
+ }
592
+ Ok ( pr) => span_bug ! ( pat. span, "tuple struct pattern resolved to {pr:?}" ) ,
593
+ } ,
581
594
PatKind :: Struct ( _, fields, has_rest_pat) => match opt_path_res. unwrap ( ) {
582
595
Ok ( ResolvedPat { ty, kind : ResolvedPatKind :: Struct { variant } } ) => self
583
596
. check_pat_struct ( pat, fields, has_rest_pat, ty, variant, expected, pat_info) ,
@@ -1443,26 +1456,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1443
1456
e. emit ( ) ;
1444
1457
}
1445
1458
1446
- fn check_pat_tuple_struct (
1459
+ fn resolve_pat_tuple_struct (
1447
1460
& self ,
1448
1461
pat : & ' tcx Pat < ' tcx > ,
1449
1462
qpath : & ' tcx hir:: QPath < ' tcx > ,
1450
- subpats : & ' tcx [ Pat < ' tcx > ] ,
1451
- ddpos : hir:: DotDotPos ,
1452
- expected : Ty < ' tcx > ,
1453
- pat_info : PatInfo < ' tcx > ,
1454
- ) -> Ty < ' tcx > {
1463
+ ) -> Result < ResolvedPat < ' tcx > , ErrorGuaranteed > {
1455
1464
let tcx = self . tcx ;
1456
- let on_error = |e| {
1457
- for pat in subpats {
1458
- self . check_pat ( pat, Ty :: new_error ( tcx, e) , pat_info) ;
1459
- }
1460
- } ;
1461
1465
let report_unexpected_res = |res : Res | {
1462
1466
let expected = "tuple struct or tuple variant" ;
1463
1467
let e = report_unexpected_variant_res ( tcx, res, None , qpath, pat. span , E0164 , expected) ;
1464
- on_error ( e) ;
1465
- e
1468
+ Err ( e)
1466
1469
} ;
1467
1470
1468
1471
// Resolve the path and check the definition for errors.
@@ -1471,25 +1474,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1471
1474
if res == Res :: Err {
1472
1475
let e = self . dcx ( ) . span_delayed_bug ( pat. span , "`Res::Err` but no error emitted" ) ;
1473
1476
self . set_tainted_by_errors ( e) ;
1474
- on_error ( e) ;
1475
- return Ty :: new_error ( tcx, e) ;
1477
+ return Err ( e) ;
1476
1478
}
1477
1479
1478
1480
// Type-check the path.
1479
1481
let ( pat_ty, res) =
1480
1482
self . instantiate_value_path ( segments, opt_ty, res, pat. span , pat. span , pat. hir_id ) ;
1481
1483
if !pat_ty. is_fn ( ) {
1482
- let e = report_unexpected_res ( res) ;
1483
- return Ty :: new_error ( tcx, e) ;
1484
+ return report_unexpected_res ( res) ;
1484
1485
}
1485
1486
1486
1487
let variant = match res {
1487
1488
Res :: Err => {
1488
1489
self . dcx ( ) . span_bug ( pat. span , "`Res::Err` but no error emitted" ) ;
1489
1490
}
1490
1491
Res :: Def ( DefKind :: AssocConst | DefKind :: AssocFn , _) => {
1491
- let e = report_unexpected_res ( res) ;
1492
- return Ty :: new_error ( tcx, e) ;
1492
+ return report_unexpected_res ( res) ;
1493
1493
}
1494
1494
Res :: Def ( DefKind :: Ctor ( _, CtorKind :: Fn ) , _) => tcx. expect_variant_res ( res) ,
1495
1495
_ => bug ! ( "unexpected pattern resolution: {:?}" , res) ,
@@ -1499,6 +1499,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1499
1499
let pat_ty = pat_ty. fn_sig ( tcx) . output ( ) ;
1500
1500
let pat_ty = pat_ty. no_bound_vars ( ) . expect ( "expected fn type" ) ;
1501
1501
1502
+ Ok ( ResolvedPat { ty : pat_ty, kind : ResolvedPatKind :: TupleStruct { res, variant } } )
1503
+ }
1504
+
1505
+ fn check_pat_tuple_struct (
1506
+ & self ,
1507
+ pat : & ' tcx Pat < ' tcx > ,
1508
+ qpath : & ' tcx hir:: QPath < ' tcx > ,
1509
+ subpats : & ' tcx [ Pat < ' tcx > ] ,
1510
+ ddpos : hir:: DotDotPos ,
1511
+ res : Res ,
1512
+ pat_ty : Ty < ' tcx > ,
1513
+ variant : & ' tcx VariantDef ,
1514
+ expected : Ty < ' tcx > ,
1515
+ pat_info : PatInfo < ' tcx > ,
1516
+ ) -> Ty < ' tcx > {
1517
+ let tcx = self . tcx ;
1518
+ let on_error = |e| {
1519
+ for pat in subpats {
1520
+ self . check_pat ( pat, Ty :: new_error ( tcx, e) , pat_info) ;
1521
+ }
1522
+ } ;
1523
+
1502
1524
// Type-check the tuple struct pattern against the expected type.
1503
1525
let diag = self . demand_eqtype_pat_diag ( pat. span , expected, pat_ty, & pat_info. top_info ) ;
1504
1526
let had_err = diag. map_err ( |diag| diag. emit ( ) ) ;
0 commit comments