@@ -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