about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-15 13:16:01 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2019-12-15 13:16:01 +0100
commitd848ce0ddf4f20bd6fbae70ad126640247f61a56 (patch)
tree49ea3981727a7efa7d63e36123db94023c886670
parentf2d6413eb276caa4d881da1aad759b02a64c6aea (diff)
downloadrust-d848ce0ddf4f20bd6fbae70ad126640247f61a56.tar.gz
rust-d848ce0ddf4f20bd6fbae70ad126640247f61a56.zip
document check_pat_slice
-rw-r--r--src/librustc_typeck/check/pat.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 71d1cd869a6..4fb57a65625 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1154,6 +1154,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.tcx.mk_ref(region, mt)
     }
 
+    /// Type check a slice pattern.
+    ///
+    /// Syntactically, these look like `[pat_0, ..., pat_n]`.
+    /// Semantically, we are type checking a pattern with structure:
+    /// ```
+    /// [before_0, ..., before_n, (slice, after_0, ... after_n)?]
+    /// ```
+    /// The type of `slice`, if it is present, depends on the `expected` type.
+    /// If `slice` is missing, then so is `after_i`.
+    /// If `slice` is present, it can still represent 0 elements.
     fn check_pat_slice(
         &self,
         span: Span,
@@ -1167,27 +1177,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         let expected_ty = self.structurally_resolved_type(span, expected);
         let (inner_ty, slice_ty) = match expected_ty.kind {
+            // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
             ty::Array(inner_ty, size) => {
                 let slice_ty = if let Some(size) = size.try_eval_usize(tcx, self.param_env) {
+                    // Now we know the length...
                     let min_len = before.len() as u64 + after.len() as u64;
                     if slice.is_none() {
+                        // ...and since there is no variable-length pattern,
+                        // we require an exact match between the number of elements
+                        // in the array pattern and as provided by the matched type.
                         if min_len != size {
                             self.error_scrutinee_inconsistent_length(span, min_len, size)
                         }
                         tcx.types.err
                     } else if let Some(rest) = size.checked_sub(min_len) {
+                        // The variable-length pattern was there,
+                        // so it has an array type with the remaining elements left as its size...
                         tcx.mk_array(inner_ty, rest)
                     } else {
+                        // ...however, in this case, there were no remaining elements.
+                        // That is, the slice pattern requires more than the array type offers.
                         self.error_scrutinee_with_rest_inconsistent_length(span, min_len, size);
                         tcx.types.err
                     }
                 } else {
+                    // No idea what the length is, which happens if we have e.g.,
+                    // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
                     self.error_scrutinee_unfixed_length(span);
                     tcx.types.err
                 };
                 (inner_ty, slice_ty)
             }
             ty::Slice(inner_ty) => (inner_ty, expected_ty),
+            // The expected type must be an array or slice, but was neither, so error.
             _ => {
                 if !expected_ty.references_error() {
                     self.error_expected_array_or_slice(span, expected_ty);
@@ -1196,12 +1218,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
+        // Type check all the patterns before `slice`.
         for elt in before {
             self.check_pat(&elt, inner_ty, def_bm, discrim_span);
         }
+        // Type check the `slice`, if present, against its expected type.
         if let Some(slice) = slice {
             self.check_pat(&slice, slice_ty, def_bm, discrim_span);
         }
+        // Type check the elements after `slice`, if present.
         for elt in after {
             self.check_pat(&elt, inner_ty, def_bm, discrim_span);
         }