@@ -812,7 +812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
812812
813813        // Determine the binding mode... 
814814        let  bm = match  user_bind_annot { 
815-             BindingMode ( ByRef :: No ,  Mutability :: Mut )  if  matches ! ( def_br ,  ByRef :: Yes ( _ ) )  => { 
815+             BindingMode ( ByRef :: No ,  Mutability :: Mut )  if  let  ByRef :: Yes ( def_br_mutbl )  = def_br  => { 
816816                // Only mention the experimental `mut_ref` feature if if we're in edition 2024 and 
817817                // using other experimental matching features compatible with it. 
818818                if  pat. span . at_least_rust_2024 ( ) 
@@ -834,22 +834,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
834834                    // `mut` resets the binding mode on edition <= 2021 
835835                    self . add_rust_2024_migration_desugared_pat ( 
836836                        pat_info. top_info . hir_id , 
837-                         pat. span , 
837+                         pat, 
838838                        ident. span , 
839-                         "requires binding by-value, but the implicit default is by-reference" , 
839+                         def_br_mutbl , 
840840                    ) ; 
841841                    BindingMode ( ByRef :: No ,  Mutability :: Mut ) 
842842                } 
843843            } 
844844            BindingMode ( ByRef :: No ,  mutbl)  => BindingMode ( def_br,  mutbl) , 
845845            BindingMode ( ByRef :: Yes ( _) ,  _)  => { 
846-                 if  matches ! ( def_br ,  ByRef :: Yes ( _ ) )  { 
846+                 if  let  ByRef :: Yes ( def_br_mutbl )  = def_br  { 
847847                    // `ref`/`ref mut` overrides the binding mode on edition <= 2021 
848848                    self . add_rust_2024_migration_desugared_pat ( 
849849                        pat_info. top_info . hir_id , 
850-                         pat. span , 
850+                         pat, 
851851                        ident. span , 
852-                         "cannot override to bind by-reference when that is the implicit default" , 
852+                         def_br_mutbl , 
853853                    ) ; 
854854                } 
855855                user_bind_annot
@@ -2386,9 +2386,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23862386                    pat_info. binding_mode  = ByRef :: No ; 
23872387                    self . add_rust_2024_migration_desugared_pat ( 
23882388                        pat_info. top_info . hir_id , 
2389-                         pat. span , 
2389+                         pat, 
23902390                        inner. span , 
2391-                         "cannot implicitly match against multiple layers of reference" , 
2391+                         inh_mut , 
23922392                    ) 
23932393                } 
23942394            } 
@@ -2778,33 +2778,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27782778fn  add_rust_2024_migration_desugared_pat ( 
27792779        & self , 
27802780        pat_id :  HirId , 
2781-         subpat_span :   Span , 
2781+         subpat :   & ' tcx   Pat < ' tcx > , 
27822782        cutoff_span :  Span , 
2783-         detailed_label :   & str , 
2783+         def_br_mutbl :   Mutability , 
27842784    )  { 
27852785        // Try to trim the span we're labeling to just the `&` or binding mode that's an issue. 
27862786        // If the subpattern's span is is from an expansion, the emitted label will not be trimmed. 
27872787        let  source_map = self . tcx . sess . source_map ( ) ; 
27882788        let  cutoff_span = source_map
2789-             . span_extend_prev_while ( cutoff_span,  char :: is_whitespace) 
2789+             . span_extend_prev_while ( cutoff_span,  |c| c . is_whitespace ( )  || c ==  '(' ) 
27902790            . unwrap_or ( cutoff_span) ; 
2791-         // Ensure we use the syntax context and thus edition of `subpat_span `; this will be a hard 
2791+         // Ensure we use the syntax context and thus edition of `subpat.span `; this will be a hard 
27922792        // error if the subpattern is of edition >= 2024. 
2793-         let  trimmed_span = subpat_span. until ( cutoff_span) . with_ctxt ( subpat_span. ctxt ( ) ) ; 
2793+         let  trimmed_span = subpat. span . until ( cutoff_span) . with_ctxt ( subpat. span . ctxt ( ) ) ; 
2794+ 
2795+         let  mut  typeck_results = self . typeck_results . borrow_mut ( ) ; 
2796+         let  mut  table = typeck_results. rust_2024_migration_desugared_pats_mut ( ) ; 
2797+         // FIXME(ref_pat_eat_one_layer_2024): The migration diagnostic doesn't know how to track the 
2798+         // default binding mode in the presence of Rule 3 or Rule 5. As a consequence, the labels it 
2799+         // gives for default binding modes are wrong, as well as suggestions based on the default 
2800+         // binding mode. This keeps it from making those suggestions, as doing so could panic. 
2801+         let  info = table. entry ( pat_id) . or_insert_with ( || ty:: Rust2024IncompatiblePatInfo  { 
2802+             primary_labels :  Vec :: new ( ) , 
2803+             bad_modifiers :  false , 
2804+             bad_ref_pats :  false , 
2805+             suggest_eliding_modes :  !self . tcx . features ( ) . ref_pat_eat_one_layer_2024 ( ) 
2806+                 && !self . tcx . features ( ) . ref_pat_eat_one_layer_2024_structural ( ) , 
2807+         } ) ; 
27942808
27952809        // Only provide a detailed label if the problematic subpattern isn't from an expansion. 
27962810        // In the case that it's from a macro, we'll add a more detailed note in the emitter. 
2797-         let  desc = if  subpat_span. from_expansion ( )  { 
2798-             "default binding mode is reset within expansion" 
2811+         let  from_expansion = subpat. span . from_expansion ( ) ; 
2812+         let  primary_label = if  from_expansion { 
2813+             // NB: This wording assumes the only expansions that can produce problematic reference 
2814+             // patterns and bindings are macros. If a desugaring or AST pass is added that can do 
2815+             // so, we may want to inspect the span's source callee or macro backtrace. 
2816+             "occurs within macro expansion" . to_owned ( ) 
27992817        }  else  { 
2800-             detailed_label
2818+             let  pat_kind = if  let  PatKind :: Binding ( user_bind_annot,  _,  _,  _)  = subpat. kind  { 
2819+                 info. bad_modifiers  |= true ; 
2820+                 // If the user-provided binding modifier doesn't match the default binding mode, we'll 
2821+                 // need to suggest reference patterns, which can affect other bindings. 
2822+                 // For simplicity, we opt to suggest making the pattern fully explicit. 
2823+                 info. suggest_eliding_modes  &=
2824+                     user_bind_annot == BindingMode ( ByRef :: Yes ( def_br_mutbl) ,  Mutability :: Not ) ; 
2825+                 "binding modifier" 
2826+             }  else  { 
2827+                 info. bad_ref_pats  |= true ; 
2828+                 // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll 
2829+                 // suggest adding them instead, which can affect the types assigned to bindings. 
2830+                 // As such, we opt to suggest making the pattern fully explicit. 
2831+                 info. suggest_eliding_modes  = false ; 
2832+                 "reference pattern" 
2833+             } ; 
2834+             let  dbm_str = match  def_br_mutbl { 
2835+                 Mutability :: Not  => "ref" , 
2836+                 Mutability :: Mut  => "ref mut" , 
2837+             } ; 
2838+             format ! ( "{pat_kind} not allowed under `{dbm_str}` default binding mode" ) 
28012839        } ; 
2802- 
2803-         self . typeck_results 
2804-             . borrow_mut ( ) 
2805-             . rust_2024_migration_desugared_pats_mut ( ) 
2806-             . entry ( pat_id) 
2807-             . or_default ( ) 
2808-             . push ( ( trimmed_span,  desc. to_owned ( ) ) ) ; 
2840+         info. primary_labels . push ( ( trimmed_span,  primary_label) ) ; 
28092841    } 
28102842} 
0 commit comments