@@ -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.
@@ -378,6 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
378380 PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
379381 Some ( self . resolve_pat_path ( * hir_id, * span, qpath) )
380382 }
383+ PatKind :: Struct ( ref qpath, ..) => Some ( self . resolve_pat_struct ( pat, qpath) ) ,
381384 _ => None ,
382385 } ;
383386 let adjust_mode = self . calc_adjust_mode ( pat, opt_path_res) ;
@@ -575,9 +578,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
575578 PatKind :: TupleStruct ( ref qpath, subpats, ddpos) => {
576579 self . check_pat_tuple_struct ( pat, qpath, subpats, ddpos, expected, pat_info)
577580 }
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+ } ,
581593 PatKind :: Guard ( pat, cond) => {
582594 self . check_pat ( pat, expected, pat_info) ;
583595 self . check_expr_has_type_or_error ( cond, self . tcx . types . bool , |_| { } ) ;
@@ -1220,27 +1232,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12201232 Ok ( ( ) )
12211233 }
12221234
1223- fn check_pat_struct (
1235+ fn resolve_pat_struct (
12241236 & self ,
12251237 pat : & ' tcx Pat < ' tcx > ,
12261238 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 > ,
12271248 fields : & ' tcx [ hir:: PatField < ' tcx > ] ,
12281249 has_rest_pat : bool ,
1250+ pat_ty : Ty < ' tcx > ,
1251+ variant : & ' tcx VariantDef ,
12291252 expected : Ty < ' tcx > ,
12301253 pat_info : PatInfo < ' tcx > ,
12311254 ) -> 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-
12441255 // Type-check the path.
12451256 let _ = self . demand_eqtype_pat ( pat. span , expected, pat_ty, & pat_info. top_info ) ;
12461257
@@ -1366,7 +1377,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13661377 pat_span : Span ,
13671378 resolved_pat : & ResolvedPat < ' tcx > ,
13681379 ) {
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+ } ;
13701383
13711384 if let Some ( span) = self . tcx . hir_res_span ( pat_res) {
13721385 e. span_label ( span, format ! ( "{} defined here" , res. descr( ) ) ) ;
0 commit comments