@@ -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.
@@ -380,6 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
380
382
PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
381
383
Some ( self . resolve_pat_path ( * hir_id, * span, qpath) )
382
384
}
385
+ PatKind :: Struct ( ref qpath, ..) => Some ( self . resolve_pat_struct ( pat, qpath) ) ,
383
386
_ => None ,
384
387
} ;
385
388
let opt_res_pat = opt_res_pat_or_err. map ( Result :: ok) . flatten ( ) ;
@@ -419,9 +422,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
419
422
PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
420
423
self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
421
424
}
422
- PatKind :: Struct ( ref qpath, fields, has_rest_pat) => {
423
- self . check_pat_struct ( pat, qpath, fields, has_rest_pat, expected, pat_info)
424
- }
425
+ PatKind :: Struct ( _, fields, has_rest_pat) => match opt_res_pat_or_err. unwrap ( ) {
426
+ Ok ( ResolvedPat { ty, kind : ResolvedPatKind :: Struct { variant } } ) => self
427
+ . check_pat_struct ( pat, fields, has_rest_pat, ty, variant, expected, pat_info) ,
428
+ Err ( guar) => {
429
+ let ty_err = Ty :: new_error ( self . tcx , guar) ;
430
+ for field in fields {
431
+ self . check_pat ( field. pat , ty_err, pat_info) ;
432
+ }
433
+ ty_err
434
+ }
435
+ Ok ( r) => span_bug ! ( pat. span, "struct pattern resolved to {r:?}" ) ,
436
+ } ,
425
437
PatKind :: Guard ( pat, cond) => {
426
438
self . check_pat ( pat, expected, pat_info) ;
427
439
self . check_expr_has_type_or_error ( cond, self . tcx . types . bool , |_| { } ) ;
@@ -1246,27 +1258,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1246
1258
Ok ( ( ) )
1247
1259
}
1248
1260
1249
- fn check_pat_struct (
1261
+ fn resolve_pat_struct (
1250
1262
& self ,
1251
1263
pat : & ' tcx Pat < ' tcx > ,
1252
1264
qpath : & hir:: QPath < ' tcx > ,
1265
+ ) -> Result < ResolvedPat < ' tcx > , ErrorGuaranteed > {
1266
+ // Resolve the path and check the definition for errors.
1267
+ let ( variant, pat_ty) = self . check_struct_path ( qpath, pat. hir_id ) ?;
1268
+ Ok ( ResolvedPat { ty : pat_ty, kind : ResolvedPatKind :: Struct { variant } } )
1269
+ }
1270
+
1271
+ fn check_pat_struct (
1272
+ & self ,
1273
+ pat : & ' tcx Pat < ' tcx > ,
1253
1274
fields : & ' tcx [ hir:: PatField < ' tcx > ] ,
1254
1275
has_rest_pat : bool ,
1276
+ pat_ty : Ty < ' tcx > ,
1277
+ variant : & ' tcx VariantDef ,
1255
1278
expected : Ty < ' tcx > ,
1256
1279
pat_info : PatInfo < ' tcx > ,
1257
1280
) -> Ty < ' tcx > {
1258
- // Resolve the path and check the definition for errors.
1259
- let ( variant, pat_ty) = match self . check_struct_path ( qpath, pat. hir_id ) {
1260
- Ok ( data) => data,
1261
- Err ( guar) => {
1262
- let err = Ty :: new_error ( self . tcx , guar) ;
1263
- for field in fields {
1264
- self . check_pat ( field. pat , err, pat_info) ;
1265
- }
1266
- return err;
1267
- }
1268
- } ;
1269
-
1270
1281
// Type-check the path.
1271
1282
let _ = self . demand_eqtype_pat ( pat. span , expected, pat_ty, & pat_info. top_info ) ;
1272
1283
@@ -1392,7 +1403,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1392
1403
pat_span : Span ,
1393
1404
resolved_pat : & ResolvedPat < ' tcx > ,
1394
1405
) {
1395
- let ResolvedPatKind :: Path { res, pat_res, segments } = resolved_pat. kind ;
1406
+ let ResolvedPatKind :: Path { res, pat_res, segments } = resolved_pat. kind else {
1407
+ span_bug ! ( pat_span, "unexpected resolution for path pattern: {resolved_pat:?}" ) ;
1408
+ } ;
1396
1409
1397
1410
if let Some ( span) = self . tcx . hir_res_span ( pat_res) {
1398
1411
e. span_label ( span, format ! ( "{} defined here" , res. descr( ) ) ) ;
0 commit comments