@@ -10,7 +10,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
10
10
use rustc_hir:: { self as hir, BindingMode , ByRef , HirId , Mutability , Pat , PatKind } ;
11
11
use rustc_infer:: infer;
12
12
use rustc_infer:: infer:: type_variable:: TypeVariableOrigin ;
13
- use rustc_lint as lint;
14
13
use rustc_middle:: mir:: interpret:: ErrorHandled ;
15
14
use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
16
15
use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
@@ -75,21 +74,23 @@ struct TopInfo<'tcx> {
75
74
/// found type `std::result::Result<_, _>`
76
75
/// ```
77
76
span : Option < Span > ,
77
+ /// The [`HirId`] of the top-level pattern.
78
+ hir_id : HirId ,
78
79
}
79
80
80
81
#[ derive( Copy , Clone ) ]
81
82
struct PatInfo < ' tcx , ' a > {
82
83
binding_mode : ByRef ,
83
84
max_ref_mutbl : MutblCap ,
84
- top_info : TopInfo < ' tcx > ,
85
- decl_origin : Option < DeclOrigin < ' a > > ,
85
+ top_info : & ' a TopInfo < ' tcx > ,
86
+ decl_origin : Option < DeclOrigin < ' tcx > > ,
86
87
87
88
/// The depth of current pattern
88
89
current_depth : u32 ,
89
90
}
90
91
91
92
impl < ' tcx > FnCtxt < ' _ , ' tcx > {
92
- fn pattern_cause ( & self , ti : TopInfo < ' tcx > , cause_span : Span ) -> ObligationCause < ' tcx > {
93
+ fn pattern_cause ( & self , ti : & TopInfo < ' tcx > , cause_span : Span ) -> ObligationCause < ' tcx > {
93
94
let code =
94
95
Pattern { span : ti. span , root_ty : ti. expected , origin_expr : ti. origin_expr . is_some ( ) } ;
95
96
self . cause ( cause_span, code)
@@ -100,7 +101,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
100
101
cause_span : Span ,
101
102
expected : Ty < ' tcx > ,
102
103
actual : Ty < ' tcx > ,
103
- ti : TopInfo < ' tcx > ,
104
+ ti : & TopInfo < ' tcx > ,
104
105
) -> Option < Diag < ' tcx > > {
105
106
let mut diag =
106
107
self . demand_eqtype_with_origin ( & self . pattern_cause ( ti, cause_span) , expected, actual) ?;
@@ -117,7 +118,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
117
118
cause_span : Span ,
118
119
expected : Ty < ' tcx > ,
119
120
actual : Ty < ' tcx > ,
120
- ti : TopInfo < ' tcx > ,
121
+ ti : & TopInfo < ' tcx > ,
121
122
) {
122
123
if let Some ( err) = self . demand_eqtype_pat_diag ( cause_span, expected, actual, ti) {
123
124
err. emit ( ) ;
@@ -193,11 +194,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193
194
origin_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
194
195
decl_origin : Option < DeclOrigin < ' tcx > > ,
195
196
) {
196
- let info = TopInfo { expected, origin_expr, span } ;
197
+ let info = TopInfo { expected, origin_expr, span, hir_id : pat . hir_id } ;
197
198
let pat_info = PatInfo {
198
199
binding_mode : ByRef :: No ,
199
200
max_ref_mutbl : MutblCap :: Mut ,
200
- top_info : info,
201
+ top_info : & info,
201
202
decl_origin,
202
203
current_depth : 0 ,
203
204
} ;
@@ -222,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
222
223
} ;
223
224
let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
224
225
let ( expected, def_bm, max_ref_mutbl, ref_pattern_already_consumed) =
225
- self . calc_default_binding_mode ( pat, expected, def_bm, adjust_mode, max_ref_mutbl) ;
226
+ self . calc_default_binding_mode ( pat, expected, def_bm, adjust_mode, max_ref_mutbl, ti ) ;
226
227
let pat_info = PatInfo {
227
228
binding_mode : def_bm,
228
229
max_ref_mutbl,
@@ -331,6 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
331
332
def_br : ByRef ,
332
333
adjust_mode : AdjustMode ,
333
334
max_ref_mutbl : MutblCap ,
335
+ top_info : & TopInfo < ' tcx > ,
334
336
) -> ( Ty < ' tcx > , ByRef , MutblCap , bool ) {
335
337
if let ByRef :: Yes ( Mutability :: Mut ) = def_br {
336
338
debug_assert ! ( max_ref_mutbl == MutblCap :: Mut ) ;
@@ -368,6 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
368
370
( new_ty, new_bm, max_ref_mutbl, false )
369
371
}
370
372
} else {
373
+ if def_br != ByRef :: No {
374
+ self . typeck_results
375
+ . borrow_mut ( )
376
+ . rust_2024_migration_desugared_pats_mut ( )
377
+ . insert ( top_info. hir_id ) ;
378
+ }
371
379
( expected, ByRef :: No , max_ref_mutbl, mutbls_match)
372
380
}
373
381
}
@@ -513,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
513
521
span : Span ,
514
522
lt : & hir:: Expr < ' tcx > ,
515
523
expected : Ty < ' tcx > ,
516
- ti : TopInfo < ' tcx > ,
524
+ ti : & TopInfo < ' tcx > ,
517
525
) -> Ty < ' tcx > {
518
526
// We've already computed the type above (when checking for a non-ref pat),
519
527
// so avoid computing it again.
@@ -583,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
583
591
lhs : Option < & ' tcx hir:: Expr < ' tcx > > ,
584
592
rhs : Option < & ' tcx hir:: Expr < ' tcx > > ,
585
593
expected : Ty < ' tcx > ,
586
- ti : TopInfo < ' tcx > ,
594
+ ti : & TopInfo < ' tcx > ,
587
595
) -> Ty < ' tcx > {
588
596
let calc_side = |opt_expr : Option < & ' tcx hir:: Expr < ' tcx > > | match opt_expr {
589
597
None => None ,
@@ -721,18 +729,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
721
729
722
730
// Determine the binding mode...
723
731
let bm = match explicit_ba {
732
+ // `mut` resets binding mode on edition <= 2021
724
733
BindingMode ( ByRef :: No , Mutability :: Mut )
725
734
if !( pat. span . at_least_rust_2024 ( )
726
735
&& self . tcx . features ( ) . mut_preserve_binding_mode_2024 )
727
736
&& matches ! ( def_br, ByRef :: Yes ( _) ) =>
728
737
{
729
- // `mut x` resets the binding mode in edition <= 2021.
730
- self . tcx . emit_node_span_lint (
731
- lint:: builtin:: DEREFERENCING_MUT_BINDING ,
732
- pat. hir_id ,
733
- pat. span ,
734
- errors:: DereferencingMutBinding { span : pat. span } ,
735
- ) ;
738
+ self . typeck_results
739
+ . borrow_mut ( )
740
+ . rust_2024_migration_desugared_pats_mut ( )
741
+ . insert ( pat_info. top_info . hir_id ) ;
736
742
BindingMode ( ByRef :: No , Mutability :: Mut )
737
743
}
738
744
BindingMode ( ByRef :: No , mutbl) => BindingMode ( def_br, mutbl) ,
@@ -796,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
796
802
span : Span ,
797
803
var_id : HirId ,
798
804
ty : Ty < ' tcx > ,
799
- ti : TopInfo < ' tcx > ,
805
+ ti : & TopInfo < ' tcx > ,
800
806
) {
801
807
let var_ty = self . local_ty ( span, var_id) ;
802
808
if let Some ( mut err) = self . demand_eqtype_pat_diag ( span, var_ty, ty, ti) {
@@ -1038,7 +1044,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1038
1044
qpath : & hir:: QPath < ' _ > ,
1039
1045
path_resolution : ( Res , Option < LoweredTy < ' tcx > > , & ' tcx [ hir:: PathSegment < ' tcx > ] ) ,
1040
1046
expected : Ty < ' tcx > ,
1041
- ti : TopInfo < ' tcx > ,
1047
+ ti : & TopInfo < ' tcx > ,
1042
1048
) -> Ty < ' tcx > {
1043
1049
let tcx = self . tcx ;
1044
1050
@@ -2169,86 +2175,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2169
2175
{
2170
2176
self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2171
2177
self . check_pat ( inner, expected, pat_info) ;
2172
- expected
2173
- } else {
2174
- let tcx = self . tcx ;
2175
- let expected = self . shallow_resolve ( expected) ;
2176
- let ( ref_ty, inner_ty, pat_info) = match self
2177
- . check_dereferenceable ( pat. span , expected, inner)
2178
- {
2179
- Ok ( ( ) ) => {
2180
- // `demand::subtype` would be good enough, but using `eqtype` turns
2181
- // out to be equally general. See (note_1) for details.
2182
-
2183
- // Take region, inner-type from expected type if we can,
2184
- // to avoid creating needless variables. This also helps with
2185
- // the bad interactions of the given hack detailed in (note_1).
2186
- debug ! ( "check_pat_ref: expected={:?}" , expected) ;
2187
- match * expected. kind ( ) {
2188
- ty:: Ref ( _, r_ty, r_mutbl) if r_mutbl == mutbl => ( expected, r_ty, pat_info) ,
2189
-
2190
- // `&` pattern eats `&mut` reference
2191
- ty:: Ref ( _, r_ty, Mutability :: Mut )
2192
- if mutbl == Mutability :: Not
2193
- && ( ( pat. span . at_least_rust_2024 ( )
2194
- && self . tcx . features ( ) . ref_pat_eat_one_layer_2024 )
2195
- || self . tcx . features ( ) . ref_pat_everywhere ) =>
2196
- {
2197
- (
2198
- expected,
2199
- r_ty,
2200
- PatInfo {
2201
- max_ref_mutbl : pat_info
2202
- . max_ref_mutbl
2203
- . cap_mutbl_to_not ( Some ( pat. span . until ( inner. span ) ) ) ,
2204
- ..pat_info
2205
- } ,
2206
- )
2207
- }
2178
+ return expected;
2179
+ }
2208
2180
2209
- _ if consumed_inherited_ref && self . tcx . features ( ) . ref_pat_everywhere => {
2210
- // We already matched against a match-ergonmics inserted reference,
2211
- // so we don't need to match against a reference from the original type.
2212
- // Save this infor for use in lowering later
2213
- self . typeck_results
2214
- . borrow_mut ( )
2215
- . skipped_ref_pats_mut ( )
2216
- . insert ( pat. hir_id ) ;
2217
- ( expected, expected, pat_info)
2218
- }
2181
+ let tcx = self . tcx ;
2182
+ let expected = self . shallow_resolve ( expected) ;
2183
+ let ( ref_ty, inner_ty, pat_info) = match self
2184
+ . check_dereferenceable ( pat. span , expected, inner)
2185
+ {
2186
+ Ok ( ( ) ) => {
2187
+ // `demand::subtype` would be good enough, but using `eqtype` turns
2188
+ // out to be equally general. See (note_1) for details.
2189
+
2190
+ // Take region, inner-type from expected type if we can,
2191
+ // to avoid creating needless variables. This also helps with
2192
+ // the bad interactions of the given hack detailed in (note_1).
2193
+ debug ! ( "check_pat_ref: expected={:?}" , expected) ;
2194
+ match * expected. kind ( ) {
2195
+ ty:: Ref ( _, r_ty, r_mutbl) if r_mutbl == mutbl => ( expected, r_ty, pat_info) ,
2196
+
2197
+ // `&` pattern eats `&mut` reference
2198
+ ty:: Ref ( _, r_ty, Mutability :: Mut )
2199
+ if mutbl == Mutability :: Not
2200
+ && ( ( pat. span . at_least_rust_2024 ( )
2201
+ && self . tcx . features ( ) . ref_pat_eat_one_layer_2024 )
2202
+ || self . tcx . features ( ) . ref_pat_everywhere ) =>
2203
+ {
2204
+ (
2205
+ expected,
2206
+ r_ty,
2207
+ PatInfo {
2208
+ max_ref_mutbl : pat_info
2209
+ . max_ref_mutbl
2210
+ . cap_mutbl_to_not ( Some ( pat. span . until ( inner. span ) ) ) ,
2211
+ ..pat_info
2212
+ } ,
2213
+ )
2214
+ }
2219
2215
2220
- _ => {
2221
- let inner_ty = self . next_ty_var ( TypeVariableOrigin {
2222
- param_def_id : None ,
2223
- span : inner. span ,
2224
- } ) ;
2225
- let ref_ty = self . new_ref_ty ( pat. span , mutbl, inner_ty) ;
2226
- debug ! ( "check_pat_ref: demanding {:?} = {:?}" , expected, ref_ty) ;
2227
- let err = self . demand_eqtype_pat_diag (
2228
- pat. span ,
2229
- expected,
2230
- ref_ty,
2231
- pat_info. top_info ,
2232
- ) ;
2216
+ _ if consumed_inherited_ref && self . tcx . features ( ) . ref_pat_everywhere => {
2217
+ // We already matched against a match-ergonmics inserted reference,
2218
+ // so we don't need to match against a reference from the original type.
2219
+ // Save this infor for use in lowering later
2220
+ self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2221
+ ( expected, expected, pat_info)
2222
+ }
2233
2223
2234
- // Look for a case like `fn foo(&foo: u32)` and suggest
2235
- // `fn foo(foo: &u32)`
2236
- if let Some ( mut err) = err {
2237
- self . borrow_pat_suggestion ( & mut err, pat) ;
2238
- err. emit ( ) ;
2239
- }
2240
- ( ref_ty, inner_ty, pat_info)
2224
+ _ => {
2225
+ let inner_ty = self . next_ty_var ( TypeVariableOrigin {
2226
+ param_def_id : None ,
2227
+ span : inner. span ,
2228
+ } ) ;
2229
+ let ref_ty = self . new_ref_ty ( pat. span , mutbl, inner_ty) ;
2230
+ debug ! ( "check_pat_ref: demanding {:?} = {:?}" , expected, ref_ty) ;
2231
+ let err = self . demand_eqtype_pat_diag (
2232
+ pat. span ,
2233
+ expected,
2234
+ ref_ty,
2235
+ pat_info. top_info ,
2236
+ ) ;
2237
+
2238
+ // Look for a case like `fn foo(&foo: u32)` and suggest
2239
+ // `fn foo(foo: &u32)`
2240
+ if let Some ( mut err) = err {
2241
+ self . borrow_pat_suggestion ( & mut err, pat) ;
2242
+ err. emit ( ) ;
2241
2243
}
2244
+ ( ref_ty, inner_ty, pat_info)
2242
2245
}
2243
2246
}
2244
- Err ( guar ) => {
2245
- let err = Ty :: new_error ( tcx , guar) ;
2246
- ( err , err , pat_info )
2247
- }
2248
- } ;
2249
- self . check_pat ( inner , inner_ty , pat_info ) ;
2250
- ref_ty
2251
- }
2247
+ }
2248
+ Err ( guar) => {
2249
+ let err = Ty :: new_error ( tcx , guar ) ;
2250
+ ( err , err , pat_info )
2251
+ }
2252
+ } ;
2253
+ self . check_pat ( inner , inner_ty , pat_info ) ;
2254
+ ref_ty
2252
2255
}
2253
2256
2254
2257
/// Create a reference type with a fresh region variable.
0 commit comments