@@ -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 > {
@@ -383,6 +384,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
383
384
Some ( self . resolve_pat_path ( * hir_id, * span, qpath) )
384
385
}
385
386
PatKind :: Struct ( ref qpath, ..) => Some ( self . resolve_pat_struct ( pat, qpath) ) ,
387
+ PatKind :: TupleStruct ( ref qpath, ..) => Some ( self . resolve_pat_tuple_struct ( pat, qpath) ) ,
386
388
_ => None ,
387
389
} ;
388
390
let opt_res_pat = opt_res_pat_or_err. map ( Result :: ok) . flatten ( ) ;
@@ -419,9 +421,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
419
421
PatKind :: Binding ( ba, var_id, ident, sub) => {
420
422
self . check_pat_ident ( pat, ba, var_id, ident, sub, expected, pat_info)
421
423
}
422
- PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
423
- self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
424
- }
424
+ PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => match opt_res_pat_or_err. unwrap ( ) {
425
+ Ok ( ResolvedPat { ty, kind : ResolvedPatKind :: TupleStruct { res, variant } } ) => self
426
+ . check_pat_tuple_struct (
427
+ pat, qpath, subpats, ddpos, res, ty, variant, expected, pat_info,
428
+ ) ,
429
+ Err ( guar) => {
430
+ let ty_err = Ty :: new_error ( self . tcx , guar) ;
431
+ for subpat in subpats {
432
+ self . check_pat ( subpat, ty_err, pat_info) ;
433
+ }
434
+ ty_err
435
+ }
436
+ Ok ( r) => span_bug ! ( pat. span, "tuple struct pattern resolved to {r:?}" ) ,
437
+ } ,
425
438
PatKind :: Struct ( _, fields, has_rest_pat) => match opt_res_pat_or_err. unwrap ( ) {
426
439
Ok ( ResolvedPat { ty, kind : ResolvedPatKind :: Struct { variant } } ) => self
427
440
. check_pat_struct ( pat, fields, has_rest_pat, ty, variant, expected, pat_info) ,
@@ -1469,26 +1482,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1469
1482
e. emit ( ) ;
1470
1483
}
1471
1484
1472
- fn check_pat_tuple_struct (
1485
+ fn resolve_pat_tuple_struct (
1473
1486
& self ,
1474
1487
pat : & ' tcx Pat < ' tcx > ,
1475
1488
qpath : & ' tcx hir:: QPath < ' tcx > ,
1476
- subpats : & ' tcx [ Pat < ' tcx > ] ,
1477
- ddpos : hir:: DotDotPos ,
1478
- expected : Ty < ' tcx > ,
1479
- pat_info : PatInfo < ' tcx > ,
1480
- ) -> Ty < ' tcx > {
1489
+ ) -> Result < ResolvedPat < ' tcx > , ErrorGuaranteed > {
1481
1490
let tcx = self . tcx ;
1482
- let on_error = |e| {
1483
- for pat in subpats {
1484
- self . check_pat ( pat, Ty :: new_error ( tcx, e) , pat_info) ;
1485
- }
1486
- } ;
1487
1491
let report_unexpected_res = |res : Res | {
1488
1492
let expected = "tuple struct or tuple variant" ;
1489
1493
let e = report_unexpected_variant_res ( tcx, res, None , qpath, pat. span , E0164 , expected) ;
1490
- on_error ( e) ;
1491
- e
1494
+ Err ( e)
1492
1495
} ;
1493
1496
1494
1497
// Resolve the path and check the definition for errors.
@@ -1497,25 +1500,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1497
1500
if res == Res :: Err {
1498
1501
let e = self . dcx ( ) . span_delayed_bug ( pat. span , "`Res::Err` but no error emitted" ) ;
1499
1502
self . set_tainted_by_errors ( e) ;
1500
- on_error ( e) ;
1501
- return Ty :: new_error ( tcx, e) ;
1503
+ return Err ( e) ;
1502
1504
}
1503
1505
1504
1506
// Type-check the path.
1505
1507
let ( pat_ty, res) =
1506
1508
self . instantiate_value_path ( segments, opt_ty, res, pat. span , pat. span , pat. hir_id ) ;
1507
1509
if !pat_ty. is_fn ( ) {
1508
- let e = report_unexpected_res ( res) ;
1509
- return Ty :: new_error ( tcx, e) ;
1510
+ return report_unexpected_res ( res) ;
1510
1511
}
1511
1512
1512
1513
let variant = match res {
1513
1514
Res :: Err => {
1514
1515
self . dcx ( ) . span_bug ( pat. span , "`Res::Err` but no error emitted" ) ;
1515
1516
}
1516
1517
Res :: Def ( DefKind :: AssocConst | DefKind :: AssocFn , _) => {
1517
- let e = report_unexpected_res ( res) ;
1518
- return Ty :: new_error ( tcx, e) ;
1518
+ return report_unexpected_res ( res) ;
1519
1519
}
1520
1520
Res :: Def ( DefKind :: Ctor ( _, CtorKind :: Fn ) , _) => tcx. expect_variant_res ( res) ,
1521
1521
_ => bug ! ( "unexpected pattern resolution: {:?}" , res) ,
@@ -1525,6 +1525,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1525
1525
let pat_ty = pat_ty. fn_sig ( tcx) . output ( ) ;
1526
1526
let pat_ty = pat_ty. no_bound_vars ( ) . expect ( "expected fn type" ) ;
1527
1527
1528
+ Ok ( ResolvedPat { ty : pat_ty, kind : ResolvedPatKind :: TupleStruct { res, variant } } )
1529
+ }
1530
+
1531
+ fn check_pat_tuple_struct (
1532
+ & self ,
1533
+ pat : & ' tcx Pat < ' tcx > ,
1534
+ qpath : & ' tcx hir:: QPath < ' tcx > ,
1535
+ subpats : & ' tcx [ Pat < ' tcx > ] ,
1536
+ ddpos : hir:: DotDotPos ,
1537
+ res : Res ,
1538
+ pat_ty : Ty < ' tcx > ,
1539
+ variant : & ' tcx VariantDef ,
1540
+ expected : Ty < ' tcx > ,
1541
+ pat_info : PatInfo < ' tcx > ,
1542
+ ) -> Ty < ' tcx > {
1543
+ let tcx = self . tcx ;
1544
+ let on_error = |e| {
1545
+ for pat in subpats {
1546
+ self . check_pat ( pat, Ty :: new_error ( tcx, e) , pat_info) ;
1547
+ }
1548
+ } ;
1549
+
1528
1550
// Type-check the tuple struct pattern against the expected type.
1529
1551
let diag = self . demand_eqtype_pat_diag ( pat. span , expected, pat_ty, & pat_info. top_info ) ;
1530
1552
let had_err = diag. map_err ( |diag| diag. emit ( ) ) ;
0 commit comments