Skip to content

Commit 5cd1599

Browse files
authored
Rollup merge of #70932 - mark-i-m:de-abuse-err-2, r=Centril
De-abuse TyKind::Error in pattern type checking r? @eddyb cc #70866 In particular, I would appreciate extra scrutiny over the soundness of these changes. Also, this will go a bit slowly because I'm going to use my other PR (#70551) to check if I missed anything.
2 parents 74e93bb + f2e4709 commit 5cd1599

File tree

1 file changed

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

1 file changed

+22
-16
lines changed

src/librustc_typeck/check/pat.rs

+22-16
Original file line numberDiff line numberDiff line change
@@ -1353,23 +1353,26 @@ 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+
// `opt_slice_ty.is_none()` => `slice.is_none()`.
1364+
// Note, though, that opt_slice_ty could be `Some(error_ty)`.
1365+
assert!(opt_slice_ty.is_some() || slice.is_none());
1366+
(element_ty, opt_slice_ty, expected)
13651367
}
1366-
ty::Slice(element_ty) => (element_ty, expected, expected),
1368+
ty::Slice(element_ty) => (element_ty, Some(expected), expected),
13671369
// The expected type must be an array or slice, but was neither, so error.
13681370
_ => {
13691371
if !expected.references_error() {
13701372
self.error_expected_array_or_slice(span, expected);
13711373
}
1372-
(err, err, err)
1374+
let err = self.tcx.types.err;
1375+
(err, Some(err), err)
13731376
}
13741377
};
13751378

@@ -1379,7 +1382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13791382
}
13801383
// Type check the `slice`, if present, against its expected type.
13811384
if let Some(slice) = slice {
1382-
self.check_pat(&slice, slice_ty, def_bm, ti);
1385+
self.check_pat(&slice, opt_slice_ty.unwrap(), def_bm, ti);
13831386
}
13841387
// Type check the elements after `slice`, if present.
13851388
for elt in after {
@@ -1390,9 +1393,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13901393

13911394
/// Type check the length of an array pattern.
13921395
///
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.
1396+
/// Returns both the type of the variable length pattern (or `None`), and the potentially
1397+
/// inferred array type. We only return `None` for the slice type if `slice.is_none()`.
13961398
fn check_array_pat_len(
13971399
&self,
13981400
span: Span,
@@ -1401,20 +1403,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14011403
slice: Option<&'tcx Pat<'tcx>>,
14021404
len: &ty::Const<'tcx>,
14031405
min_len: u64,
1404-
) -> (Ty<'tcx>, Ty<'tcx>) {
1406+
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
14051407
if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
14061408
// Now we know the length...
14071409
if slice.is_none() {
14081410
// ...and since there is no variable-length pattern,
14091411
// we require an exact match between the number of elements
14101412
// in the array pattern and as provided by the matched type.
1411-
if min_len != len {
1412-
self.error_scrutinee_inconsistent_length(span, min_len, len);
1413+
if min_len == len {
1414+
return (None, arr_ty);
14131415
}
1416+
1417+
self.error_scrutinee_inconsistent_length(span, min_len, len);
14141418
} else if let Some(pat_len) = len.checked_sub(min_len) {
14151419
// The variable-length pattern was there,
14161420
// 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);
1421+
return (Some(self.tcx.mk_array(element_ty, pat_len)), arr_ty);
14181422
} else {
14191423
// ...however, in this case, there were no remaining elements.
14201424
// That is, the slice pattern requires more than the array type offers.
@@ -1425,14 +1429,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14251429
// which we can use to infer the length of the array.
14261430
let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
14271431
self.demand_eqtype(span, updated_arr_ty, arr_ty);
1428-
return (self.tcx.types.err, updated_arr_ty);
1432+
return (None, updated_arr_ty);
14291433
} else {
14301434
// We have a variable-length pattern and don't know the array length.
14311435
// This happens if we have e.g.,
14321436
// `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
14331437
self.error_scrutinee_unfixed_length(span);
14341438
}
1435-
(self.tcx.types.err, arr_ty)
1439+
1440+
// If we get here, we must have emitted an error.
1441+
(Some(self.tcx.types.err), arr_ty)
14361442
}
14371443

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

0 commit comments

Comments
 (0)