Skip to content

Commit f9a691f

Browse files
committed
de-abuse TyKind::Error: handle empty slices in array patterns
1 parent d249d75 commit f9a691f

File tree

1 file changed

+16
-15
lines changed
  • src/librustc_typeck/check

1 file changed

+16
-15
lines changed

src/librustc_typeck/check/pat.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,32 +1353,34 @@ 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+
// we can get opt_slice_ty == None in cases that are not an error, e.g. if the
1364+
// slice covers 0 elements or if slice is None.
1365+
(element_ty, opt_slice_ty, expected)
13651366
}
1366-
ty::Slice(element_ty) => (element_ty, expected, expected),
1367+
ty::Slice(element_ty) => (element_ty, Some(expected), expected),
13671368
// The expected type must be an array or slice, but was neither, so error.
13681369
_ => {
13691370
if !expected.references_error() {
13701371
self.error_expected_array_or_slice(span, expected);
13711372
}
1372-
(err, err, err)
1373+
let err = self.tcx.types.err;
1374+
(err, None, err)
13731375
}
13741376
};
13751377

13761378
// Type check all the patterns before `slice`.
13771379
for elt in before {
13781380
self.check_pat(&elt, element_ty, def_bm, ti);
13791381
}
1380-
// Type check the `slice`, if present, against its expected type.
1381-
if let Some(slice) = slice {
1382+
// Type check the `slice`, if present, against its expected type, if there is one.
1383+
if let (Some(slice), Some(slice_ty)) = (slice, opt_slice_ty) {
13821384
self.check_pat(&slice, slice_ty, def_bm, ti);
13831385
}
13841386
// Type check the elements after `slice`, if present.
@@ -1390,9 +1392,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13901392

13911393
/// Type check the length of an array pattern.
13921394
///
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.
1395+
/// Returns both the type of the variable length pattern (or `None`), and the potentially
1396+
/// inferred array type.
13961397
fn check_array_pat_len(
13971398
&self,
13981399
span: Span,
@@ -1401,7 +1402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14011402
slice: Option<&'tcx Pat<'tcx>>,
14021403
len: &ty::Const<'tcx>,
14031404
min_len: u64,
1404-
) -> (Ty<'tcx>, Ty<'tcx>) {
1405+
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
14051406
if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
14061407
// Now we know the length...
14071408
if slice.is_none() {
@@ -1414,7 +1415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14141415
} else if let Some(pat_len) = len.checked_sub(min_len) {
14151416
// The variable-length pattern was there,
14161417
// 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);
1418+
return (Some(self.tcx.mk_array(element_ty, pat_len)), arr_ty);
14181419
} else {
14191420
// ...however, in this case, there were no remaining elements.
14201421
// That is, the slice pattern requires more than the array type offers.
@@ -1425,14 +1426,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14251426
// which we can use to infer the length of the array.
14261427
let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
14271428
self.demand_eqtype(span, updated_arr_ty, arr_ty);
1428-
return (self.tcx.types.err, updated_arr_ty);
1429+
return (None, updated_arr_ty);
14291430
} else {
14301431
// We have a variable-length pattern and don't know the array length.
14311432
// This happens if we have e.g.,
14321433
// `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
14331434
self.error_scrutinee_unfixed_length(span);
14341435
}
1435-
(self.tcx.types.err, arr_ty)
1436+
(None, arr_ty)
14361437
}
14371438

14381439
fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {

0 commit comments

Comments
 (0)