@@ -1154,6 +1154,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11541154 self . tcx . mk_ref ( region, mt)
11551155 }
11561156
1157+ /// Type check a slice pattern.
1158+ ///
1159+ /// Syntactically, these look like `[pat_0, ..., pat_n]`.
1160+ /// Semantically, we are type checking a pattern with structure:
1161+ /// ```
1162+ /// [before_0, ..., before_n, (slice, after_0, ... after_n)?]
1163+ /// ```
1164+ /// The type of `slice`, if it is present, depends on the `expected` type.
1165+ /// If `slice` is missing, then so is `after_i`.
1166+ /// If `slice` is present, it can still represent 0 elements.
11571167 fn check_pat_slice (
11581168 & self ,
11591169 span : Span ,
@@ -1167,27 +1177,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11671177 let tcx = self . tcx ;
11681178 let expected_ty = self . structurally_resolved_type ( span, expected) ;
11691179 let ( inner_ty, slice_ty) = match expected_ty. kind {
1180+ // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
11701181 ty:: Array ( inner_ty, size) => {
11711182 let slice_ty = if let Some ( size) = size. try_eval_usize ( tcx, self . param_env ) {
1183+ // Now we know the length...
11721184 let min_len = before. len ( ) as u64 + after. len ( ) as u64 ;
11731185 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.
11741189 if min_len != size {
11751190 self . error_scrutinee_inconsistent_length ( span, min_len, size)
11761191 }
11771192 tcx. types . err
11781193 } 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...
11791196 tcx. mk_array ( inner_ty, rest)
11801197 } else {
1198+ // ...however, in this case, there were no remaining elements.
1199+ // That is, the slice pattern requires more than the array type offers.
11811200 self . error_scrutinee_with_rest_inconsistent_length ( span, min_len, size) ;
11821201 tcx. types . err
11831202 }
11841203 } 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`.
11851206 self . error_scrutinee_unfixed_length ( span) ;
11861207 tcx. types . err
11871208 } ;
11881209 ( inner_ty, slice_ty)
11891210 }
11901211 ty:: Slice ( inner_ty) => ( inner_ty, expected_ty) ,
1212+ // The expected type must be an array or slice, but was neither, so error.
11911213 _ => {
11921214 if !expected_ty. references_error ( ) {
11931215 self . error_expected_array_or_slice ( span, expected_ty) ;
@@ -1196,12 +1218,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11961218 }
11971219 } ;
11981220
1221+ // Type check all the patterns before `slice`.
11991222 for elt in before {
12001223 self . check_pat ( & elt, inner_ty, def_bm, discrim_span) ;
12011224 }
1225+ // Type check the `slice`, if present, against its expected type.
12021226 if let Some ( slice) = slice {
12031227 self . check_pat ( & slice, slice_ty, def_bm, discrim_span) ;
12041228 }
1229+ // Type check the elements after `slice`, if present.
12051230 for elt in after {
12061231 self . check_pat ( & elt, inner_ty, def_bm, discrim_span) ;
12071232 }
0 commit comments