@@ -83,6 +83,9 @@ struct PatInfo<'tcx, 'a> {
83
83
binding_mode : BindingMode ,
84
84
top_info : TopInfo < ' tcx > ,
85
85
decl_origin : Option < DeclOrigin < ' a > > ,
86
+
87
+ parent_kind : Option < PatKind < ' tcx > > ,
88
+ current_kind : Option < PatKind < ' tcx > > ,
86
89
}
87
90
88
91
impl < ' tcx > FnCtxt < ' _ , ' tcx > {
@@ -152,7 +155,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
152
155
decl_origin : Option < DeclOrigin < ' tcx > > ,
153
156
) {
154
157
let info = TopInfo { expected, origin_expr, span } ;
155
- let pat_info = PatInfo { binding_mode : INITIAL_BM , top_info : info, decl_origin } ;
158
+ let pat_info = PatInfo {
159
+ binding_mode : INITIAL_BM ,
160
+ top_info : info,
161
+ decl_origin,
162
+ parent_kind : None ,
163
+ current_kind : None ,
164
+ } ;
156
165
self . check_pat ( pat, expected, pat_info) ;
157
166
}
158
167
@@ -163,7 +172,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163
172
/// Conversely, inside this module, `check_pat_top` should never be used.
164
173
#[ instrument( level = "debug" , skip( self , pat_info) ) ]
165
174
fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' tcx , ' _ > ) {
166
- let PatInfo { binding_mode : def_bm, top_info : ti, .. } = pat_info;
175
+ let PatInfo { binding_mode : def_bm, top_info : ti, current_kind, .. } = pat_info;
176
+
167
177
let path_res = match & pat. kind {
168
178
PatKind :: Path ( qpath) => Some (
169
179
self . resolve_ty_and_res_fully_qualified_call ( qpath, pat. hir_id , pat. span , None ) ,
@@ -172,8 +182,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172
182
} ;
173
183
let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
174
184
let ( expected, def_bm) = self . calc_default_binding_mode ( pat, expected, def_bm, adjust_mode) ;
175
- let pat_info =
176
- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin : pat_info. decl_origin } ;
185
+ let pat_info = PatInfo {
186
+ binding_mode : def_bm,
187
+ top_info : ti,
188
+ decl_origin : pat_info. decl_origin ,
189
+ parent_kind : current_kind,
190
+ current_kind : Some ( pat. kind ) ,
191
+ } ;
177
192
178
193
let ty = match pat. kind {
179
194
PatKind :: Wild | PatKind :: Err ( _) => expected,
@@ -1046,14 +1061,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1046
1061
expected : Ty < ' tcx > ,
1047
1062
pat_info : PatInfo < ' tcx , ' _ > ,
1048
1063
) -> Ty < ' tcx > {
1049
- let PatInfo { binding_mode : def_bm, top_info : ti, decl_origin } = pat_info;
1064
+ let PatInfo { binding_mode : def_bm, top_info : ti, decl_origin, parent_kind, current_kind } =
1065
+ pat_info;
1050
1066
let tcx = self . tcx ;
1051
1067
let on_error = |e| {
1052
1068
for pat in subpats {
1053
1069
self . check_pat (
1054
1070
pat,
1055
1071
Ty :: new_error ( tcx, e) ,
1056
- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin } ,
1072
+ PatInfo {
1073
+ binding_mode : def_bm,
1074
+ top_info : ti,
1075
+ decl_origin,
1076
+ parent_kind,
1077
+ current_kind,
1078
+ } ,
1057
1079
) ;
1058
1080
}
1059
1081
} ;
@@ -1120,7 +1142,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1120
1142
self . check_pat (
1121
1143
subpat,
1122
1144
field_ty,
1123
- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin } ,
1145
+ PatInfo {
1146
+ binding_mode : def_bm,
1147
+ top_info : ti,
1148
+ decl_origin,
1149
+ parent_kind,
1150
+ current_kind,
1151
+ } ,
1124
1152
) ;
1125
1153
1126
1154
self . tcx . check_stability (
@@ -2134,7 +2162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2134
2162
// The expected type must be an array or slice, but was neither, so error.
2135
2163
_ => {
2136
2164
let guar = expected. error_reported ( ) . err ( ) . unwrap_or_else ( || {
2137
- self . error_expected_array_or_slice ( span, expected, pat_info. top_info )
2165
+ self . error_expected_array_or_slice ( span, expected, pat_info)
2138
2166
} ) ;
2139
2167
let err = Ty :: new_error ( self . tcx , guar) ;
2140
2168
( err, Some ( err) , err)
@@ -2273,8 +2301,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2273
2301
& self ,
2274
2302
span : Span ,
2275
2303
expected_ty : Ty < ' tcx > ,
2276
- ti : TopInfo < ' tcx > ,
2304
+ pat_info : PatInfo < ' tcx , ' _ > ,
2277
2305
) -> ErrorGuaranteed {
2306
+ let PatInfo { top_info : ti, parent_kind, .. } = pat_info;
2307
+
2278
2308
let mut err = struct_span_code_err ! (
2279
2309
self . dcx( ) ,
2280
2310
span,
@@ -2292,9 +2322,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2292
2322
&& let Some ( _) = ti. origin_expr
2293
2323
&& let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span)
2294
2324
{
2295
- let ty = self . resolve_vars_if_possible ( ti. expected ) ;
2296
- let is_slice_or_array_or_vector = self . is_slice_or_array_or_vector ( ty) ;
2297
- match is_slice_or_array_or_vector. 1 . kind ( ) {
2325
+ let resolved_ty = self . resolve_vars_if_possible ( ti. expected ) ;
2326
+ let ( is_slice_or_array_or_vector, resolved_ty) =
2327
+ self . is_slice_or_array_or_vector ( resolved_ty) ;
2328
+ match resolved_ty. kind ( ) {
2298
2329
ty:: Adt ( adt_def, _)
2299
2330
if self . tcx . is_diagnostic_item ( sym:: Option , adt_def. did ( ) )
2300
2331
|| self . tcx . is_diagnostic_item ( sym:: Result , adt_def. did ( ) ) =>
@@ -2309,7 +2340,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2309
2340
}
2310
2341
_ => ( ) ,
2311
2342
}
2312
- if is_slice_or_array_or_vector. 0 {
2343
+
2344
+ let enclosure_is_struct =
2345
+ parent_kind. map_or ( false , |enclosure| matches ! ( enclosure, PatKind :: Struct ( ..) ) ) ;
2346
+
2347
+ if is_slice_or_array_or_vector && !enclosure_is_struct {
2313
2348
err. span_suggestion (
2314
2349
span,
2315
2350
"consider slicing here" ,
0 commit comments