@@ -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> {
27782778 fn 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