@@ -1353,23 +1353,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1353
1353
def_bm : BindingMode ,
1354
1354
ti : TopInfo < ' tcx > ,
1355
1355
) -> Ty < ' tcx > {
1356
- let err = self . tcx . types . err ;
1357
1356
let expected = self . structurally_resolved_type ( span, expected) ;
1358
- let ( element_ty, slice_ty , inferred) = match expected. kind {
1357
+ let ( element_ty, opt_slice_ty , inferred) = match expected. kind {
1359
1358
// An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
1360
1359
ty:: Array ( element_ty, len) => {
1361
1360
let min = before. len ( ) as u64 + after. len ( ) as u64 ;
1362
- let ( slice_ty , expected) =
1361
+ let ( opt_slice_ty , expected) =
1363
1362
self . check_array_pat_len ( span, element_ty, expected, slice, len, min) ;
1364
- ( element_ty, slice_ty, expected)
1363
+ // `opt_slice_ty.is_none()` => `slice.is_none()`.
1364
+ // Note, though, that opt_slice_ty could be `Some(error_ty)`.
1365
+ assert ! ( opt_slice_ty. is_some( ) || slice. is_none( ) ) ;
1366
+ ( element_ty, opt_slice_ty, expected)
1365
1367
}
1366
- ty:: Slice ( element_ty) => ( element_ty, expected, expected) ,
1368
+ ty:: Slice ( element_ty) => ( element_ty, Some ( expected) , expected) ,
1367
1369
// The expected type must be an array or slice, but was neither, so error.
1368
1370
_ => {
1369
1371
if !expected. references_error ( ) {
1370
1372
self . error_expected_array_or_slice ( span, expected) ;
1371
1373
}
1372
- ( err, err, err)
1374
+ let err = self . tcx . types . err ;
1375
+ ( err, Some ( err) , err)
1373
1376
}
1374
1377
} ;
1375
1378
@@ -1379,7 +1382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1379
1382
}
1380
1383
// Type check the `slice`, if present, against its expected type.
1381
1384
if let Some ( slice) = slice {
1382
- self . check_pat ( & slice, slice_ty , def_bm, ti) ;
1385
+ self . check_pat ( & slice, opt_slice_ty . unwrap ( ) , def_bm, ti) ;
1383
1386
}
1384
1387
// Type check the elements after `slice`, if present.
1385
1388
for elt in after {
@@ -1390,9 +1393,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1390
1393
1391
1394
/// Type check the length of an array pattern.
1392
1395
///
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
+ /// Returns both the type of the variable length pattern (or `None`), and the potentially
1397
+ /// inferred array type. We only return `None` for the slice type if `slice.is_none()`.
1396
1398
fn check_array_pat_len (
1397
1399
& self ,
1398
1400
span : Span ,
@@ -1401,20 +1403,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1401
1403
slice : Option < & ' tcx Pat < ' tcx > > ,
1402
1404
len : & ty:: Const < ' tcx > ,
1403
1405
min_len : u64 ,
1404
- ) -> ( Ty < ' tcx > , Ty < ' tcx > ) {
1406
+ ) -> ( Option < Ty < ' tcx > > , Ty < ' tcx > ) {
1405
1407
if let Some ( len) = len. try_eval_usize ( self . tcx , self . param_env ) {
1406
1408
// Now we know the length...
1407
1409
if slice. is_none ( ) {
1408
1410
// ...and since there is no variable-length pattern,
1409
1411
// we require an exact match between the number of elements
1410
1412
// in the array pattern and as provided by the matched type.
1411
- if min_len ! = len {
1412
- self . error_scrutinee_inconsistent_length ( span , min_len , len ) ;
1413
+ if min_len = = len {
1414
+ return ( None , arr_ty ) ;
1413
1415
}
1416
+
1417
+ self . error_scrutinee_inconsistent_length ( span, min_len, len) ;
1414
1418
} else if let Some ( pat_len) = len. checked_sub ( min_len) {
1415
1419
// The variable-length pattern was there,
1416
1420
// so it has an array type with the remaining elements left as its size...
1417
- return ( self . tcx . mk_array ( element_ty, pat_len) , arr_ty) ;
1421
+ return ( Some ( self . tcx . mk_array ( element_ty, pat_len) ) , arr_ty) ;
1418
1422
} else {
1419
1423
// ...however, in this case, there were no remaining elements.
1420
1424
// That is, the slice pattern requires more than the array type offers.
@@ -1425,14 +1429,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1425
1429
// which we can use to infer the length of the array.
1426
1430
let updated_arr_ty = self . tcx . mk_array ( element_ty, min_len) ;
1427
1431
self . demand_eqtype ( span, updated_arr_ty, arr_ty) ;
1428
- return ( self . tcx . types . err , updated_arr_ty) ;
1432
+ return ( None , updated_arr_ty) ;
1429
1433
} else {
1430
1434
// We have a variable-length pattern and don't know the array length.
1431
1435
// This happens if we have e.g.,
1432
1436
// `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
1433
1437
self . error_scrutinee_unfixed_length ( span) ;
1434
1438
}
1435
- ( self . tcx . types . err , arr_ty)
1439
+
1440
+ // If we get here, we must have emitted an error.
1441
+ ( Some ( self . tcx . types . err ) , arr_ty)
1436
1442
}
1437
1443
1438
1444
fn error_scrutinee_inconsistent_length ( & self , span : Span , min_len : u64 , size : u64 ) {
0 commit comments