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