@@ -1174,38 +1174,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11741174 def_bm : BindingMode ,
11751175 discrim_span : Option < Span > ,
11761176 ) -> Ty < ' tcx > {
1177- let tcx = self . tcx ;
1177+ let err = self . tcx . types . err ;
11781178 let expected = self . structurally_resolved_type ( span, expected) ;
11791179 let ( inner_ty, slice_ty, expected) = match expected. kind {
11801180 // 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) ) ;
12091185 ( inner_ty, slice_ty, expected)
12101186 }
12111187 ty:: Slice ( inner_ty) => ( inner_ty, expected, expected) ,
@@ -1214,7 +1190,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12141190 if !expected. references_error ( ) {
12151191 self . error_expected_array_or_slice ( span, expected) ;
12161192 }
1217- ( tcx . types . err , tcx . types . err , tcx . types . err )
1193+ ( err, err, err)
12181194 }
12191195 } ;
12201196
@@ -1233,6 +1209,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12331209 expected
12341210 }
12351211
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+
12361249 fn error_scrutinee_inconsistent_length ( & self , span : Span , min_len : u64 , size : u64 ) {
12371250 struct_span_err ! (
12381251 self . tcx. sess,
0 commit comments