@@ -277,12 +277,14 @@ struct ResolvedPat<'tcx> {
277
277
#[ derive( Clone , Copy , Debug ) ]
278
278
enum ResolvedPatKind < ' tcx > {
279
279
Path { res : Res , pat_res : Res , segments : & ' tcx [ hir:: PathSegment < ' tcx > ] } ,
280
+ Struct { variant : & ' tcx VariantDef } ,
280
281
}
281
282
282
283
impl < ' tcx > ResolvedPat < ' tcx > {
283
284
fn adjust_mode ( & self ) -> AdjustMode {
284
- let ResolvedPatKind :: Path { res, .. } = self . kind ;
285
- if matches ! ( res, Res :: Def ( DefKind :: Const | DefKind :: AssocConst , _) ) {
285
+ if let ResolvedPatKind :: Path { res, .. } = self . kind
286
+ && matches ! ( res, Res :: Def ( DefKind :: Const | DefKind :: AssocConst , _) )
287
+ {
286
288
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
287
289
// Peeling the reference types too early will cause type checking failures.
288
290
// Although it would be possible to *also* peel the types of the constants too.
@@ -378,6 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
378
380
PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
379
381
Some ( self . resolve_pat_path ( * hir_id, * span, qpath) )
380
382
}
383
+ PatKind :: Struct ( ref qpath, ..) => Some ( self . resolve_pat_struct ( pat, qpath) ) ,
381
384
_ => None ,
382
385
} ;
383
386
let adjust_mode = self . calc_adjust_mode ( pat, opt_path_res) ;
@@ -575,9 +578,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
575
578
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
576
579
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
577
580
}
578
- PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
579
- self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
580
- }
581
+ PatKind :: Struct ( _, fields, has_rest_pat) => match opt_path_res. unwrap ( ) {
582
+ Ok ( ResolvedPat { ty, kind : ResolvedPatKind :: Struct { variant } } ) => self
583
+ . check_pat_struct ( pat, fields, has_rest_pat, ty, variant, expected, pat_info) ,
584
+ Err ( guar) => {
585
+ let ty_err = Ty :: new_error ( self . tcx , guar) ;
586
+ for field in fields {
587
+ self . check_pat ( field. pat , ty_err, pat_info) ;
588
+ }
589
+ ty_err
590
+ }
591
+ Ok ( pr) => span_bug ! ( pat. span, "struct pattern resolved to {pr:?}" ) ,
592
+ } ,
581
593
PatKind :: Guard ( pat, cond) => {
582
594
self . check_pat ( pat, expected, pat_info) ;
583
595
self . check_expr_has_type_or_error ( cond, self . tcx . types . bool , |_| { } ) ;
@@ -1220,27 +1232,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1220
1232
Ok ( ( ) )
1221
1233
}
1222
1234
1223
- fn check_pat_struct (
1235
+ fn resolve_pat_struct (
1224
1236
& self ,
1225
1237
pat : & ' tcx Pat < ' tcx > ,
1226
1238
qpath : & hir:: QPath < ' tcx > ,
1239
+ ) -> Result < ResolvedPat < ' tcx > , ErrorGuaranteed > {
1240
+ // Resolve the path and check the definition for errors.
1241
+ let ( variant, pat_ty) = self . check_struct_path ( qpath, pat. hir_id ) ?;
1242
+ Ok ( ResolvedPat { ty : pat_ty, kind : ResolvedPatKind :: Struct { variant } } )
1243
+ }
1244
+
1245
+ fn check_pat_struct (
1246
+ & self ,
1247
+ pat : & ' tcx Pat < ' tcx > ,
1227
1248
fields : & ' tcx [ hir:: PatField < ' tcx > ] ,
1228
1249
has_rest_pat : bool ,
1250
+ pat_ty : Ty < ' tcx > ,
1251
+ variant : & ' tcx VariantDef ,
1229
1252
expected : Ty < ' tcx > ,
1230
1253
pat_info : PatInfo < ' tcx > ,
1231
1254
) -> Ty < ' tcx > {
1232
- // Resolve the path and check the definition for errors.
1233
- let ( variant, pat_ty) = match self . check_struct_path ( qpath, pat. hir_id ) {
1234
- Ok ( data) => data,
1235
- Err ( guar) => {
1236
- let err = Ty :: new_error ( self . tcx , guar) ;
1237
- for field in fields {
1238
- self . check_pat ( field. pat , err, pat_info) ;
1239
- }
1240
- return err;
1241
- }
1242
- } ;
1243
-
1244
1255
// Type-check the path.
1245
1256
let _ = self . demand_eqtype_pat ( pat. span , expected, pat_ty, & pat_info. top_info ) ;
1246
1257
@@ -1366,7 +1377,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1366
1377
pat_span : Span ,
1367
1378
resolved_pat : & ResolvedPat < ' tcx > ,
1368
1379
) {
1369
- let ResolvedPatKind :: Path { res, pat_res, segments } = resolved_pat. kind ;
1380
+ let ResolvedPatKind :: Path { res, pat_res, segments } = resolved_pat. kind else {
1381
+ span_bug ! ( pat_span, "unexpected resolution for path pattern: {resolved_pat:?}" ) ;
1382
+ } ;
1370
1383
1371
1384
if let Some ( span) = self . tcx . hir_res_span ( pat_res) {
1372
1385
e. span_label ( span, format ! ( "{} defined here" , res. descr( ) ) ) ;
0 commit comments