@@ -699,7 +699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
699699
700700 // Determine the binding mode...
701701 let bm = match user_bind_annot {
702- BindingMode ( ByRef :: No , Mutability :: Mut ) if matches ! ( def_br , ByRef :: Yes ( _ ) ) => {
702+ BindingMode ( ByRef :: No , Mutability :: Mut ) if let ByRef :: Yes ( def_br_mutbl ) = def_br => {
703703 if pat. span . at_least_rust_2024 ( )
704704 && ( self . tcx . features ( ) . ref_pat_eat_one_layer_2024 ( )
705705 || self . tcx . features ( ) . ref_pat_eat_one_layer_2024_structural ( ) )
@@ -719,22 +719,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
719719 // `mut` resets the binding mode on edition <= 2021
720720 self . add_rust_2024_migration_desugared_pat (
721721 pat_info. top_info . hir_id ,
722- pat. span ,
722+ pat,
723723 ident. span ,
724- "requires binding by-value, but the implicit default is by-reference" ,
724+ def_br_mutbl ,
725725 ) ;
726726 BindingMode ( ByRef :: No , Mutability :: Mut )
727727 }
728728 }
729729 BindingMode ( ByRef :: No , mutbl) => BindingMode ( def_br, mutbl) ,
730730 BindingMode ( ByRef :: Yes ( _) , _) => {
731- if matches ! ( def_br , ByRef :: Yes ( _ ) ) {
731+ if let ByRef :: Yes ( def_br_mutbl ) = def_br {
732732 // `ref`/`ref mut` overrides the binding mode on edition <= 2021
733733 self . add_rust_2024_migration_desugared_pat (
734734 pat_info. top_info . hir_id ,
735- pat. span ,
735+ pat,
736736 ident. span ,
737- "cannot override to bind by-reference when that is the implicit default" ,
737+ def_br_mutbl ,
738738 ) ;
739739 }
740740 user_bind_annot
@@ -2263,13 +2263,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22632263 }
22642264 } else {
22652265 // Reset binding mode on old editions
2266- if pat_info . binding_mode != ByRef :: No {
2266+ if let ByRef :: Yes ( inh_mut ) = pat_info . binding_mode {
22672267 pat_info. binding_mode = ByRef :: No ;
22682268 self . add_rust_2024_migration_desugared_pat (
22692269 pat_info. top_info . hir_id ,
2270- pat. span ,
2270+ pat,
22712271 inner. span ,
2272- "cannot implicitly match against multiple layers of reference" ,
2272+ inh_mut ,
22732273 )
22742274 }
22752275 }
@@ -2635,33 +2635,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26352635 fn add_rust_2024_migration_desugared_pat (
26362636 & self ,
26372637 pat_id : HirId ,
2638- subpat_span : Span ,
2638+ subpat : & ' tcx Pat < ' tcx > ,
26392639 cutoff_span : Span ,
2640- detailed_label : & str ,
2640+ def_br_mutbl : Mutability ,
26412641 ) {
26422642 // Try to trim the span we're labeling to just the `&` or binding mode that's an issue.
26432643 // If the subpattern's span is is from an expansion, the emitted label will not be trimmed.
26442644 let source_map = self . tcx . sess . source_map ( ) ;
26452645 let cutoff_span = source_map
2646- . span_extend_prev_while ( cutoff_span, char :: is_whitespace)
2646+ . span_extend_prev_while ( cutoff_span, |c| c . is_whitespace ( ) || c == '(' )
26472647 . unwrap_or ( cutoff_span) ;
2648- // Ensure we use the syntax context and thus edition of `subpat_span `; this will be a hard
2648+ // Ensure we use the syntax context and thus edition of `subpat.span `; this will be a hard
26492649 // error if the subpattern is of edition >= 2024.
2650- let trimmed_span = subpat_span. until ( cutoff_span) . with_ctxt ( subpat_span. ctxt ( ) ) ;
2650+ let trimmed_span = subpat. span . until ( cutoff_span) . with_ctxt ( subpat. span . ctxt ( ) ) ;
2651+
2652+ let mut typeck_results = self . typeck_results . borrow_mut ( ) ;
2653+ let mut table = typeck_results. rust_2024_migration_desugared_pats_mut ( ) ;
2654+ // FIXME(ref_pat_eat_one_layer_2024): The migration diagnostic doesn't know how to track the
2655+ // default binding mode in the presence of Rule 3 or Rule 5. As a consequence, the labels it
2656+ // gives for default binding modes are wrong, as well as suggestions based on the default
2657+ // binding mode. This keeps it from making those suggestions, as doing so could panic.
2658+ let info = table. entry ( pat_id) . or_insert_with ( || ty:: Rust2024IncompatiblePatInfo {
2659+ primary_labels : Vec :: new ( ) ,
2660+ bad_modifiers : false ,
2661+ bad_ref_pats : false ,
2662+ suggest_eliding_modes : !self . tcx . features ( ) . ref_pat_eat_one_layer_2024 ( )
2663+ && !self . tcx . features ( ) . ref_pat_eat_one_layer_2024_structural ( ) ,
2664+ } ) ;
26512665
26522666 // Only provide a detailed label if the problematic subpattern isn't from an expansion.
26532667 // In the case that it's from a macro, we'll add a more detailed note in the emitter.
2654- let desc = if subpat_span. from_expansion ( ) {
2655- "default binding mode is reset within expansion"
2668+ let from_expansion = subpat. span . from_expansion ( ) ;
2669+ let primary_label = if from_expansion {
2670+ // NB: This wording assumes the only expansions that can produce problematic reference
2671+ // patterns and bindings are macros. If a desugaring or AST pass is added that can do
2672+ // so, we may want to inspect the span's source callee or macro backtrace.
2673+ "occurs within macro expansion" . to_owned ( )
26562674 } else {
2657- detailed_label
2675+ let pat_kind = if let PatKind :: Binding ( user_bind_annot, _, _, _) = subpat. kind {
2676+ info. bad_modifiers |= true ;
2677+ // If the user-provided binding modifier doesn't match the default binding mode, we'll
2678+ // need to suggest reference patterns, which can affect other bindings.
2679+ // For simplicity, we opt to suggest making the pattern fully explicit.
2680+ info. suggest_eliding_modes &=
2681+ user_bind_annot == BindingMode ( ByRef :: Yes ( def_br_mutbl) , Mutability :: Not ) ;
2682+ "binding modifier"
2683+ } else {
2684+ info. bad_ref_pats |= true ;
2685+ // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
2686+ // suggest adding them instead, which can affect the types assigned to bindings.
2687+ // As such, we opt to suggest making the pattern fully explicit.
2688+ info. suggest_eliding_modes = false ;
2689+ "reference pattern"
2690+ } ;
2691+ let dbm_str = match def_br_mutbl {
2692+ Mutability :: Not => "ref" ,
2693+ Mutability :: Mut => "ref mut" ,
2694+ } ;
2695+ format ! ( "{pat_kind} not allowed under `{dbm_str}` default binding mode" )
26582696 } ;
2659-
2660- self . typeck_results
2661- . borrow_mut ( )
2662- . rust_2024_migration_desugared_pats_mut ( )
2663- . entry ( pat_id)
2664- . or_default ( )
2665- . push ( ( trimmed_span, desc. to_owned ( ) ) ) ;
2697+ info. primary_labels . push ( ( trimmed_span, primary_label) ) ;
26662698 }
26672699}
0 commit comments