@@ -1355,16 +1355,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1355
1355
) -> Ty<'tcx> {
1356
1356
let err = self.tcx.types.err;
1357
1357
let expected = self.structurally_resolved_type(span, expected);
1358
- let ( inner_ty , slice_ty, expected) = match expected. kind {
1358
+ let (element_ty , slice_ty, expected) = match expected.kind {
1359
1359
// An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
1360
- ty:: Array ( inner_ty , len) => {
1360
+ ty::Array(element_ty , len) => {
1361
1361
let min = before.len() as u64 + after.len() as u64;
1362
- let slice_ty = self
1363
- . check_array_pat_len ( span, slice, len, min)
1364
- . map_or ( err, |len| self . tcx . mk_array ( inner_ty, len) ) ;
1365
- ( inner_ty, slice_ty, expected)
1362
+ let (slice_ty, expected) =
1363
+ self.check_array_pat_len(span, element_ty, expected, slice, len, min);
1364
+ (element_ty, slice_ty, expected)
1366
1365
}
1367
- ty:: Slice ( inner_ty ) => ( inner_ty , expected, expected) ,
1366
+ ty::Slice(element_ty ) => (element_ty , expected, expected),
1368
1367
// The expected type must be an array or slice, but was neither, so error.
1369
1368
_ => {
1370
1369
if !expected.references_error() {
@@ -1376,30 +1375,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1376
1375
1377
1376
// Type check all the patterns before `slice`.
1378
1377
for elt in before {
1379
- self . check_pat ( & elt, inner_ty , def_bm, ti) ;
1378
+ self.check_pat(&elt, element_ty , def_bm, ti);
1380
1379
}
1381
1380
// Type check the `slice`, if present, against its expected type.
1382
1381
if let Some(slice) = slice {
1383
1382
self.check_pat(&slice, slice_ty, def_bm, ti);
1384
1383
}
1385
1384
// Type check the elements after `slice`, if present.
1386
1385
for elt in after {
1387
- self . check_pat ( & elt, inner_ty , def_bm, ti) ;
1386
+ self.check_pat(&elt, element_ty , def_bm, ti);
1388
1387
}
1389
1388
expected
1390
1389
}
1391
1390
1392
1391
/// Type check the length of an array pattern.
1393
1392
///
1394
- /// Return the length of the variable length pattern,
1395
- /// if it exists and there are no errors.
1393
+ /// Returns both the type of the variable length pattern
1394
+ /// (or `tcx.err` in case there is none),
1395
+ /// and the potentially inferred array type.
1396
1396
fn check_array_pat_len(
1397
1397
&self,
1398
1398
span: Span,
1399
+ element_ty: Ty<'tcx>,
1400
+ arr_ty: Ty<'tcx>,
1399
1401
slice: Option<&'tcx Pat<'tcx>>,
1400
1402
len: &ty::Const<'tcx>,
1401
1403
min_len: u64,
1402
- ) -> Option < u64 > {
1404
+ ) -> (Ty<'tcx>, Ty<'tcx>) {
1403
1405
if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
1404
1406
// Now we know the length...
1405
1407
if slice.is_none() {
@@ -1409,21 +1411,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1409
1411
if min_len != len {
1410
1412
self.error_scrutinee_inconsistent_length(span, min_len, len);
1411
1413
}
1412
- } else if let r @ Some ( _ ) = len. checked_sub ( min_len) {
1414
+ } else if let Some(pat_len ) = len.checked_sub(min_len) {
1413
1415
// The variable-length pattern was there,
1414
1416
// so it has an array type with the remaining elements left as its size...
1415
- return r ;
1417
+ return (self.tcx.mk_array(element_ty, pat_len), arr_ty) ;
1416
1418
} else {
1417
1419
// ...however, in this case, there were no remaining elements.
1418
1420
// That is, the slice pattern requires more than the array type offers.
1419
1421
self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len);
1420
1422
}
1423
+ } else if slice.is_none() {
1424
+ // We have a pattern with a fixed length,
1425
+ // which we can use to infer the length of the array.
1426
+ // of the array.
1427
+ let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
1428
+ self.demand_eqtype(span, updated_arr_ty, arr_ty);
1429
+ return (self.tcx.types.err, updated_arr_ty);
1421
1430
} else {
1422
- // No idea what the length is, which happens if we have e.g.,
1423
- // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
1431
+ // We have a variable-length pattern and don't know the array length.
1432
+ // This happens if we have e.g.,
1433
+ // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
1424
1434
self.error_scrutinee_unfixed_length(span);
1425
1435
}
1426
- None
1436
+ (self.tcx.types.err, arr_ty)
1427
1437
}
1428
1438
1429
1439
fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
0 commit comments