@@ -1353,23 +1353,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13531353 def_bm : BindingMode ,
13541354 ti : TopInfo < ' tcx > ,
13551355 ) -> Ty < ' tcx > {
1356- let err = self . tcx . types . err ;
13571356 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 {
13591358 // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
13601359 ty:: Array ( element_ty, len) => {
13611360 let min = before. len ( ) as u64 + after. len ( ) as u64 ;
1362- let ( slice_ty , expected) =
1361+ let ( opt_slice_ty , expected) =
13631362 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)
13651367 }
1366- ty:: Slice ( element_ty) => ( element_ty, expected, expected) ,
1368+ ty:: Slice ( element_ty) => ( element_ty, Some ( expected) , expected) ,
13671369 // The expected type must be an array or slice, but was neither, so error.
13681370 _ => {
13691371 if !expected. references_error ( ) {
13701372 self . error_expected_array_or_slice ( span, expected) ;
13711373 }
1372- ( err, err, err)
1374+ let err = self . tcx . types . err ;
1375+ ( err, Some ( err) , err)
13731376 }
13741377 } ;
13751378
@@ -1379,7 +1382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13791382 }
13801383 // Type check the `slice`, if present, against its expected type.
13811384 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) ;
13831386 }
13841387 // Type check the elements after `slice`, if present.
13851388 for elt in after {
@@ -1390,9 +1393,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13901393
13911394 /// Type check the length of an array pattern.
13921395 ///
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()`.
13961398 fn check_array_pat_len (
13971399 & self ,
13981400 span : Span ,
@@ -1401,20 +1403,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14011403 slice : Option < & ' tcx Pat < ' tcx > > ,
14021404 len : & ty:: Const < ' tcx > ,
14031405 min_len : u64 ,
1404- ) -> ( Ty < ' tcx > , Ty < ' tcx > ) {
1406+ ) -> ( Option < Ty < ' tcx > > , Ty < ' tcx > ) {
14051407 if let Some ( len) = len. try_eval_usize ( self . tcx , self . param_env ) {
14061408 // Now we know the length...
14071409 if slice. is_none ( ) {
14081410 // ...and since there is no variable-length pattern,
14091411 // we require an exact match between the number of elements
14101412 // 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 ) ;
14131415 }
1416+
1417+ self . error_scrutinee_inconsistent_length ( span, min_len, len) ;
14141418 } else if let Some ( pat_len) = len. checked_sub ( min_len) {
14151419 // The variable-length pattern was there,
14161420 // 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) ;
14181422 } else {
14191423 // ...however, in this case, there were no remaining elements.
14201424 // That is, the slice pattern requires more than the array type offers.
@@ -1425,14 +1429,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14251429 // which we can use to infer the length of the array.
14261430 let updated_arr_ty = self . tcx . mk_array ( element_ty, min_len) ;
14271431 self . demand_eqtype ( span, updated_arr_ty, arr_ty) ;
1428- return ( self . tcx . types . err , updated_arr_ty) ;
1432+ return ( None , updated_arr_ty) ;
14291433 } else {
14301434 // We have a variable-length pattern and don't know the array length.
14311435 // This happens if we have e.g.,
14321436 // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
14331437 self . error_scrutinee_unfixed_length ( span) ;
14341438 }
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)
14361442 }
14371443
14381444 fn error_scrutinee_inconsistent_length ( & self , span : Span , min_len : u64 , size : u64 ) {
0 commit comments