@@ -79,11 +79,12 @@ struct TopInfo<'tcx> {
79
79
span : Option < Span > ,
80
80
}
81
81
82
- #[ derive( Copy , Clone ) ]
82
+ #[ derive( Clone ) ]
83
83
struct PatInfo < ' tcx , ' a > {
84
84
binding_mode : BindingMode ,
85
85
top_info : TopInfo < ' tcx > ,
86
86
decl_origin : Option < DeclOrigin < ' a > > ,
87
+ history : Vec < PatKind < ' tcx > > ,
87
88
}
88
89
89
90
impl < ' tcx > FnCtxt < ' _ , ' tcx > {
@@ -153,7 +154,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
153
154
decl_origin : Option < DeclOrigin < ' tcx > > ,
154
155
) {
155
156
let info = TopInfo { expected, origin_expr, span } ;
156
- let pat_info = PatInfo { binding_mode : INITIAL_BM , top_info : info, decl_origin } ;
157
+ let pat_info =
158
+ PatInfo { binding_mode : INITIAL_BM , top_info : info, decl_origin, history : Vec :: new ( ) } ;
157
159
self . check_pat ( pat, expected, pat_info) ;
158
160
}
159
161
@@ -164,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
164
166
/// Conversely, inside this module, `check_pat_top` should never be used.
165
167
#[ instrument( level = "debug" , skip( self , pat_info) ) ]
166
168
fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' tcx , ' _ > ) {
167
- let PatInfo { binding_mode : def_bm, top_info : ti, .. } = pat_info;
169
+ let PatInfo { binding_mode : def_bm, top_info : ti, mut history , .. } = pat_info;
168
170
let path_res = match & pat. kind {
169
171
PatKind :: Path ( qpath) => Some (
170
172
self . resolve_ty_and_res_fully_qualified_call ( qpath, pat. hir_id , pat. span , None ) ,
@@ -173,8 +175,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173
175
} ;
174
176
let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
175
177
let ( expected, def_bm) = self . calc_default_binding_mode ( pat, expected, def_bm, adjust_mode) ;
176
- let pat_info =
177
- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin : pat_info. decl_origin } ;
178
+ history. push ( pat. kind ) ;
179
+ let pat_info = PatInfo {
180
+ binding_mode : def_bm,
181
+ top_info : ti,
182
+ decl_origin : pat_info. decl_origin ,
183
+ history,
184
+ } ;
178
185
179
186
let ty = match pat. kind {
180
187
PatKind :: Wild | PatKind :: Err ( _) => expected,
@@ -196,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
196
203
}
197
204
PatKind :: Or ( pats) => {
198
205
for pat in pats {
199
- self . check_pat ( pat, expected, pat_info) ;
206
+ self . check_pat ( pat, expected, pat_info. clone ( ) ) ;
200
207
}
201
208
expected
202
209
}
@@ -869,7 +876,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
869
876
Err ( guar) => {
870
877
let err = Ty :: new_error ( self . tcx , guar) ;
871
878
for field in fields {
872
- self . check_pat ( field. pat , err, pat_info) ;
879
+ self . check_pat ( field. pat , err, pat_info. clone ( ) ) ;
873
880
}
874
881
return err;
875
882
}
@@ -1047,14 +1054,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1047
1054
expected : Ty < ' tcx > ,
1048
1055
pat_info : PatInfo < ' tcx , ' _ > ,
1049
1056
) -> Ty < ' tcx > {
1050
- let PatInfo { binding_mode : def_bm, top_info : ti, decl_origin } = pat_info;
1057
+ let PatInfo { binding_mode : def_bm, top_info : ti, decl_origin, history } = pat_info;
1051
1058
let tcx = self . tcx ;
1052
1059
let on_error = |e| {
1053
1060
for pat in subpats {
1054
1061
self . check_pat (
1055
1062
pat,
1056
1063
Ty :: new_error ( tcx, e) ,
1057
- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin } ,
1064
+ PatInfo {
1065
+ binding_mode : def_bm,
1066
+ top_info : ti,
1067
+ decl_origin,
1068
+ history : history. clone ( ) ,
1069
+ } ,
1058
1070
) ;
1059
1071
}
1060
1072
} ;
@@ -1124,7 +1136,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1124
1136
self . check_pat (
1125
1137
subpat,
1126
1138
field_ty,
1127
- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin } ,
1139
+ PatInfo {
1140
+ binding_mode : def_bm,
1141
+ top_info : ti,
1142
+ decl_origin,
1143
+ history : history. clone ( ) ,
1144
+ } ,
1128
1145
) ;
1129
1146
1130
1147
self . tcx . check_stability (
@@ -1336,12 +1353,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1336
1353
// further errors being emitted when using the bindings. #50333
1337
1354
let element_tys_iter = ( 0 ..max_len) . map ( |_| Ty :: new_error ( tcx, reported) ) ;
1338
1355
for ( _, elem) in elements. iter ( ) . enumerate_and_adjust ( max_len, ddpos) {
1339
- self . check_pat ( elem, Ty :: new_error ( tcx, reported) , pat_info) ;
1356
+ self . check_pat ( elem, Ty :: new_error ( tcx, reported) , pat_info. clone ( ) ) ;
1340
1357
}
1341
1358
Ty :: new_tup_from_iter ( tcx, element_tys_iter)
1342
1359
} else {
1343
1360
for ( i, elem) in elements. iter ( ) . enumerate_and_adjust ( max_len, ddpos) {
1344
- self . check_pat ( elem, element_tys[ i] , pat_info) ;
1361
+ self . check_pat ( elem, element_tys[ i] , pat_info. clone ( ) ) ;
1345
1362
}
1346
1363
pat_ty
1347
1364
}
@@ -1402,7 +1419,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1402
1419
}
1403
1420
} ;
1404
1421
1405
- self . check_pat ( field. pat , field_ty, pat_info) ;
1422
+ self . check_pat ( field. pat , field_ty, pat_info. clone ( ) ) ;
1406
1423
}
1407
1424
1408
1425
let mut unmentioned_fields = variant
@@ -2138,7 +2155,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2138
2155
// The expected type must be an array or slice, but was neither, so error.
2139
2156
_ => {
2140
2157
let guar = expected. error_reported ( ) . err ( ) . unwrap_or_else ( || {
2141
- self . error_expected_array_or_slice ( span, expected, pat_info. top_info )
2158
+ self . error_expected_array_or_slice ( span, expected, pat_info. clone ( ) )
2142
2159
} ) ;
2143
2160
let err = Ty :: new_error ( self . tcx , guar) ;
2144
2161
( err, Some ( err) , err)
@@ -2147,15 +2164,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2147
2164
2148
2165
// Type check all the patterns before `slice`.
2149
2166
for elt in before {
2150
- self . check_pat ( elt, element_ty, pat_info) ;
2167
+ self . check_pat ( elt, element_ty, pat_info. clone ( ) ) ;
2151
2168
}
2152
2169
// Type check the `slice`, if present, against its expected type.
2153
2170
if let Some ( slice) = slice {
2154
- self . check_pat ( slice, opt_slice_ty. unwrap ( ) , pat_info) ;
2171
+ self . check_pat ( slice, opt_slice_ty. unwrap ( ) , pat_info. clone ( ) ) ;
2155
2172
}
2156
2173
// Type check the elements after `slice`, if present.
2157
2174
for elt in after {
2158
- self . check_pat ( elt, element_ty, pat_info) ;
2175
+ self . check_pat ( elt, element_ty, pat_info. clone ( ) ) ;
2159
2176
}
2160
2177
inferred
2161
2178
}
@@ -2277,8 +2294,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2277
2294
& self ,
2278
2295
span : Span ,
2279
2296
expected_ty : Ty < ' tcx > ,
2280
- ti : TopInfo < ' tcx > ,
2297
+ pat_info : PatInfo < ' tcx , ' _ > ,
2281
2298
) -> ErrorGuaranteed {
2299
+ let PatInfo { top_info : ti, history, .. } = pat_info;
2300
+
2282
2301
let mut err = struct_span_code_err ! (
2283
2302
self . dcx( ) ,
2284
2303
span,
@@ -2296,9 +2315,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2296
2315
&& let Some ( _) = ti. origin_expr
2297
2316
&& let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span)
2298
2317
{
2299
- let ty = self . resolve_vars_if_possible ( ti. expected ) ;
2300
- let is_slice_or_array_or_vector = self . is_slice_or_array_or_vector ( ty) ;
2301
- match is_slice_or_array_or_vector. 1 . kind ( ) {
2318
+ let resolved_ty = self . resolve_vars_if_possible ( ti. expected ) ;
2319
+ let ( is_slice_or_array_or_vector, resolved_ty) =
2320
+ self . is_slice_or_array_or_vector ( resolved_ty) ;
2321
+ match resolved_ty. kind ( ) {
2302
2322
ty:: Adt ( adt_def, _)
2303
2323
if self . tcx . is_diagnostic_item ( sym:: Option , adt_def. did ( ) )
2304
2324
|| self . tcx . is_diagnostic_item ( sym:: Result , adt_def. did ( ) ) =>
@@ -2313,7 +2333,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2313
2333
}
2314
2334
_ => ( ) ,
2315
2335
}
2316
- if is_slice_or_array_or_vector. 0 {
2336
+
2337
+ let enclosure_is_struct = history
2338
+ . get ( history. len ( ) - 2 )
2339
+ . map_or ( false , |enclosure| matches ! ( enclosure, PatKind :: Struct ( ..) ) ) ;
2340
+
2341
+ if is_slice_or_array_or_vector && !enclosure_is_struct {
2317
2342
err. span_suggestion (
2318
2343
span,
2319
2344
"consider slicing here" ,
0 commit comments