@@ -1174,38 +1174,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1174
1174
def_bm : BindingMode ,
1175
1175
discrim_span : Option < Span > ,
1176
1176
) -> Ty < ' tcx > {
1177
- let tcx = self . tcx ;
1177
+ let err = self . tcx . types . err ;
1178
1178
let expected = self . structurally_resolved_type ( span, expected) ;
1179
1179
let ( inner_ty, slice_ty, expected) = match expected. kind {
1180
1180
// An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
1181
- ty:: Array ( inner_ty, size) => {
1182
- let slice_ty = if let Some ( size) = size. try_eval_usize ( tcx, self . param_env ) {
1183
- // Now we know the length...
1184
- let min_len = before. len ( ) as u64 + after. len ( ) as u64 ;
1185
- if slice. is_none ( ) {
1186
- // ...and since there is no variable-length pattern,
1187
- // we require an exact match between the number of elements
1188
- // in the array pattern and as provided by the matched type.
1189
- if min_len != size {
1190
- self . error_scrutinee_inconsistent_length ( span, min_len, size)
1191
- }
1192
- tcx. types . err
1193
- } else if let Some ( rest) = size. checked_sub ( min_len) {
1194
- // The variable-length pattern was there,
1195
- // so it has an array type with the remaining elements left as its size...
1196
- tcx. mk_array ( inner_ty, rest)
1197
- } else {
1198
- // ...however, in this case, there were no remaining elements.
1199
- // That is, the slice pattern requires more than the array type offers.
1200
- self . error_scrutinee_with_rest_inconsistent_length ( span, min_len, size) ;
1201
- tcx. types . err
1202
- }
1203
- } else {
1204
- // No idea what the length is, which happens if we have e.g.,
1205
- // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
1206
- self . error_scrutinee_unfixed_length ( span) ;
1207
- tcx. types . err
1208
- } ;
1181
+ ty:: Array ( inner_ty, len) => {
1182
+ let min = before. len ( ) as u64 + after. len ( ) as u64 ;
1183
+ let slice_ty = self . check_array_pat_len ( span, slice, len, min)
1184
+ . map_or ( err, |len| self . tcx . mk_array ( inner_ty, len) ) ;
1209
1185
( inner_ty, slice_ty, expected)
1210
1186
}
1211
1187
ty:: Slice ( inner_ty) => ( inner_ty, expected, expected) ,
@@ -1214,7 +1190,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1214
1190
if !expected. references_error ( ) {
1215
1191
self . error_expected_array_or_slice ( span, expected) ;
1216
1192
}
1217
- ( tcx . types . err , tcx . types . err , tcx . types . err )
1193
+ ( err, err, err)
1218
1194
}
1219
1195
} ;
1220
1196
@@ -1233,6 +1209,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1233
1209
expected
1234
1210
}
1235
1211
1212
+ /// Type check the length of an array pattern.
1213
+ ///
1214
+ /// Return the length of the variable length pattern,
1215
+ /// if it exists and there are no errors.
1216
+ fn check_array_pat_len (
1217
+ & self ,
1218
+ span : Span ,
1219
+ slice : Option < & ' tcx Pat > ,
1220
+ len : & ty:: Const < ' tcx > ,
1221
+ min_len : u64 ,
1222
+ ) -> Option < u64 > {
1223
+ if let Some ( len) = len. try_eval_usize ( self . tcx , self . param_env ) {
1224
+ // Now we know the length...
1225
+ if slice. is_none ( ) {
1226
+ // ...and since there is no variable-length pattern,
1227
+ // we require an exact match between the number of elements
1228
+ // in the array pattern and as provided by the matched type.
1229
+ if min_len != len {
1230
+ self . error_scrutinee_inconsistent_length ( span, min_len, len) ;
1231
+ }
1232
+ } else if let r @ Some ( _) = len. checked_sub ( min_len) {
1233
+ // The variable-length pattern was there,
1234
+ // so it has an array type with the remaining elements left as its size...
1235
+ return r;
1236
+ } else {
1237
+ // ...however, in this case, there were no remaining elements.
1238
+ // That is, the slice pattern requires more than the array type offers.
1239
+ self . error_scrutinee_with_rest_inconsistent_length ( span, min_len, len) ;
1240
+ }
1241
+ } else {
1242
+ // No idea what the length is, which happens if we have e.g.,
1243
+ // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
1244
+ self . error_scrutinee_unfixed_length ( span) ;
1245
+ }
1246
+ None
1247
+ }
1248
+
1236
1249
fn error_scrutinee_inconsistent_length ( & self , span : Span , min_len : u64 , size : u64 ) {
1237
1250
struct_span_err ! (
1238
1251
self . tcx. sess,
0 commit comments