Skip to content

Commit d848ce0

Browse files
committed
document check_pat_slice
1 parent f2d6413 commit d848ce0

File tree

1 file changed

+25
-0
lines changed
  • src/librustc_typeck/check

1 file changed

+25
-0
lines changed

src/librustc_typeck/check/pat.rs

+25
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)