1
Fork 0

Don't use max_slice_length when subtracting from VarLenSlice

This alters error messages slightly, but that'll be improved later
This commit is contained in:
Nadrieril 2019-11-03 23:10:33 +00:00
parent 909ec37028
commit b66973043e
2 changed files with 23 additions and 14 deletions

View file

@ -658,7 +658,6 @@ impl<'tcx> Constructor<'tcx> {
// anything in `other_ctors`. // anything in `other_ctors`.
fn subtract_ctors( fn subtract_ctors(
&self, &self,
pcx: PatCtxt<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
other_ctors: &Vec<Constructor<'tcx>>, other_ctors: &Vec<Constructor<'tcx>>,
@ -681,11 +680,7 @@ impl<'tcx> Constructor<'tcx> {
if other_ctors.iter().any(overlaps) { vec![] } else { vec![self.clone()] } if other_ctors.iter().any(overlaps) { vec![] } else { vec![self.clone()] }
} }
VarLenSlice(_) => { VarLenSlice(_) => {
let mut remaining_ctors = if let VarLenSlice(len) = self { let mut remaining_ctors = vec![self.clone()];
(*len..pcx.max_slice_length + 1).map(FixedLenSlice).collect()
} else {
vec![self.clone()]
};
// For each used ctor, subtract from the current set of constructors. // For each used ctor, subtract from the current set of constructors.
// Naming: we remove the "neg" constructors from the "pos" ones. // Naming: we remove the "neg" constructors from the "pos" ones.
@ -704,6 +699,23 @@ impl<'tcx> Constructor<'tcx> {
smallvec![pos_ctor] smallvec![pos_ctor]
} }
} }
(VarLenSlice(pos_len), VarLenSlice(neg_len)) => {
if neg_len <= pos_len {
smallvec![]
} else {
(*pos_len..*neg_len).map(FixedLenSlice).collect()
}
}
(VarLenSlice(pos_len), FixedLenSlice(neg_len)) => {
if neg_len < pos_len {
smallvec![pos_ctor]
} else {
(*pos_len..*neg_len)
.map(FixedLenSlice)
.chain(Some(VarLenSlice(neg_len + 1)))
.collect()
}
}
_ if pos_ctor == *neg_ctor => smallvec![], _ if pos_ctor == *neg_ctor => smallvec![],
_ => smallvec![pos_ctor], _ => smallvec![pos_ctor],
} }
@ -1456,7 +1468,6 @@ impl<'tcx> IntRange<'tcx> {
// A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`. // A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`.
struct MissingConstructors<'tcx> { struct MissingConstructors<'tcx> {
pcx: PatCtxt<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
all_ctors: Vec<Constructor<'tcx>>, all_ctors: Vec<Constructor<'tcx>>,
@ -1465,13 +1476,12 @@ struct MissingConstructors<'tcx> {
impl<'tcx> MissingConstructors<'tcx> { impl<'tcx> MissingConstructors<'tcx> {
fn new( fn new(
pcx: PatCtxt<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
all_ctors: Vec<Constructor<'tcx>>, all_ctors: Vec<Constructor<'tcx>>,
used_ctors: Vec<Constructor<'tcx>>, used_ctors: Vec<Constructor<'tcx>>,
) -> Self { ) -> Self {
MissingConstructors { pcx, tcx, param_env, all_ctors, used_ctors } MissingConstructors { tcx, param_env, all_ctors, used_ctors }
} }
fn into_inner(self) -> (Vec<Constructor<'tcx>>, Vec<Constructor<'tcx>>) { fn into_inner(self) -> (Vec<Constructor<'tcx>>, Vec<Constructor<'tcx>>) {
@ -1490,7 +1500,7 @@ impl<'tcx> MissingConstructors<'tcx> {
/// Iterate over all_ctors \ used_ctors /// Iterate over all_ctors \ used_ctors
fn iter<'a>(&'a self) -> impl Iterator<Item = Constructor<'tcx>> + Captures<'a> { fn iter<'a>(&'a self) -> impl Iterator<Item = Constructor<'tcx>> + Captures<'a> {
self.all_ctors.iter().flat_map(move |req_ctor| { self.all_ctors.iter().flat_map(move |req_ctor| {
req_ctor.subtract_ctors(self.pcx, self.tcx, self.param_env, &self.used_ctors) req_ctor.subtract_ctors(self.tcx, self.param_env, &self.used_ctors)
}) })
} }
} }
@ -1633,8 +1643,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
// non-wildcard patterns in the current column. To determine if // non-wildcard patterns in the current column. To determine if
// the set is empty, we can check that `.peek().is_none()`, so // the set is empty, we can check that `.peek().is_none()`, so
// we only fully construct them on-demand, because they're rarely used and can be big. // we only fully construct them on-demand, because they're rarely used and can be big.
let missing_ctors = let missing_ctors = MissingConstructors::new(cx.tcx, cx.param_env, all_ctors, used_ctors);
MissingConstructors::new(pcx, cx.tcx, cx.param_env, all_ctors, used_ctors);
debug!( debug!(
"missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", "missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}",

View file

@ -6,11 +6,11 @@ LL | match buf {
| |
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered error[E0004]: non-exhaustive patterns: `&[]` not covered
--> $DIR/match-byte-array-patterns-2.rs:10:11 --> $DIR/match-byte-array-patterns-2.rs:10:11
| |
LL | match buf { LL | match buf {
| ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered | ^^^ pattern `&[]` not covered
| |
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms