@@ -277,12 +277,14 @@ struct ResolvedPat<'tcx> {
277277#[ derive( Clone , Copy , Debug ) ]
278278enum ResolvedPatKind < ' tcx > {
279279 Path { res : Res , pat_res : Res , segments : & ' tcx [ hir:: PathSegment < ' tcx > ] } ,
280+ Struct { variant : & ' tcx VariantDef } ,
280281}
281282
282283impl < ' tcx > ResolvedPat < ' tcx > {
283284 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+ {
286288 // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
287289 // Peeling the reference types too early will cause type checking failures.
288290 // Although it would be possible to *also* peel the types of the constants too.
@@ -380,6 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
380382 PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
381383 Some ( self . resolve_pat_path ( * hir_id, * span, qpath) )
382384 }
385+ PatKind :: Struct ( ref qpath, ..) => Some ( self . resolve_pat_struct ( pat, qpath) ) ,
383386 _ => None ,
384387 } ;
385388 let opt_res_pat = opt_res_pat_or_err. map ( Result :: ok) . flatten ( ) ;
@@ -419,9 +422,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
419422 PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
420423 self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
421424 }
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+ } ,
425437 PatKind :: Guard ( pat, cond) => {
426438 self . check_pat ( pat, expected, pat_info) ;
427439 self . check_expr_has_type_or_error ( cond, self . tcx . types . bool , |_| { } ) ;
@@ -1246,27 +1258,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12461258 Ok ( ( ) )
12471259 }
12481260
1249- fn check_pat_struct (
1261+ fn resolve_pat_struct (
12501262 & self ,
12511263 pat : & ' tcx Pat < ' tcx > ,
12521264 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 > ,
12531274 fields : & ' tcx [ hir:: PatField < ' tcx > ] ,
12541275 has_rest_pat : bool ,
1276+ pat_ty : Ty < ' tcx > ,
1277+ variant : & ' tcx VariantDef ,
12551278 expected : Ty < ' tcx > ,
12561279 pat_info : PatInfo < ' tcx > ,
12571280 ) -> 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-
12701281 // Type-check the path.
12711282 let _ = self . demand_eqtype_pat ( pat. span , expected, pat_ty, & pat_info. top_info ) ;
12721283
@@ -1392,7 +1403,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13921403 pat_span : Span ,
13931404 resolved_pat : & ResolvedPat < ' tcx > ,
13941405 ) {
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+ } ;
13961409
13971410 if let Some ( span) = self . tcx . hir_res_span ( pat_res) {
13981411 e. span_label ( span, format ! ( "{} defined here" , res. descr( ) ) ) ;
0 commit comments