From fa4a4d3edaf48e9a08f6357765eef8714b424cdf Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 17 Nov 2019 22:25:51 +0000 Subject: [PATCH 1/4] Add some tests --- ...413-constants-and-slices-exhaustiveness.rs | 15 +++++++++++ ...constants-and-slices-exhaustiveness.stderr | 14 ++++++++++ .../pattern/usefulness/slice-pattern-const.rs | 7 +++++ .../usefulness/slice-pattern-const.stderr | 8 +++++- .../slice-patterns-exhaustiveness.rs | 22 ++++++++++++++++ .../slice-patterns-exhaustiveness.stderr | 26 ++++++++++++++++++- .../usefulness/slice-patterns-reachability.rs | 2 +- 7 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs create mode 100644 src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs new file mode 100644 index 0000000000000..cca4173e3ef1c --- /dev/null +++ b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs @@ -0,0 +1,15 @@ +#![feature(slice_patterns)] +#![deny(unreachable_patterns)] + +const C0: &'static [u8] = b"\x00"; + +fn main() { + let x: &[u8] = &[0]; + match x { + &[] => {} + &[1..=255] => {} + // this shouldn't be unreachable + C0 => {} //~ unreachable pattern + &[_, _, ..] => {} + } +} diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr new file mode 100644 index 0000000000000..74421b4085c61 --- /dev/null +++ b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/65413-constants-and-slices-exhaustiveness.rs:12:9 + | +LL | C0 => {} + | ^^ + | +note: lint level defined here + --> $DIR/65413-constants-and-slices-exhaustiveness.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pattern/usefulness/slice-pattern-const.rs b/src/test/ui/pattern/usefulness/slice-pattern-const.rs index f0a04513f91fb..89195d5b11e52 100644 --- a/src/test/ui/pattern/usefulness/slice-pattern-const.rs +++ b/src/test/ui/pattern/usefulness/slice-pattern-const.rs @@ -44,4 +44,11 @@ fn main() { b"" => (), //~ ERROR unreachable pattern _ => (), //~ ERROR unreachable pattern } + + const CONST1: &[bool; 1] = &[true]; + match &[false] { + CONST1 => {} + [true] => {} //~ ERROR unreachable pattern + [false] => {} + } } diff --git a/src/test/ui/pattern/usefulness/slice-pattern-const.stderr b/src/test/ui/pattern/usefulness/slice-pattern-const.stderr index 2dd10a0478ab9..d274d6d7c678b 100644 --- a/src/test/ui/pattern/usefulness/slice-pattern-const.stderr +++ b/src/test/ui/pattern/usefulness/slice-pattern-const.stderr @@ -52,5 +52,11 @@ error: unreachable pattern LL | _ => (), | ^ -error: aborting due to 8 previous errors +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:51:9 + | +LL | [true] => {} + | ^^^^^^ + +error: aborting due to 9 previous errors diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs index eb3dfac950f79..88a47fc074f5c 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs +++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs @@ -82,4 +82,26 @@ fn main() { [_, _] => {} [false, .., false] => {} } + + const CONST: &[bool] = &[true]; + match s { + //~^ ERROR `&[..]` not covered + CONST => {} + } + match s { + //~^ ERROR `&[true]` not covered + [] => {}, + [false] => {}, + CONST => {}, + [_, _, ..] => {} + } + const CONST1: &[bool; 1] = &[true]; + match s1 { + //~^ ERROR `&[..]` not covered + CONST1 => {} + } + match s1 { + CONST1 => {} + [false] => {} + } } diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr index ebadedccfea21..2295de02ed532 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr +++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -102,6 +102,30 @@ LL | match s { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 13 previous errors +error[E0004]: non-exhaustive patterns: `&[..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:87:11 + | +LL | match s { + | ^ pattern `&[..]` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `&[true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:91:11 + | +LL | match s { + | ^ pattern `&[true]` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `&[..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:99:11 + | +LL | match s1 { + | ^^ pattern `&[..]` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs index 35d9dc91aee1c..cd229a0fcbee4 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs +++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs @@ -2,7 +2,7 @@ #![deny(unreachable_patterns)] fn main() { - let s: &[bool] = &[true; 0]; + let s: &[bool] = &[]; match s { [true, ..] => {} From 5510f5589eac9504f7fdbd5673ff64e2bddd88ab Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 17 Nov 2019 22:43:06 +0000 Subject: [PATCH 2/4] Use appropriate constructor for const slices --- src/librustc_mir/hair/pattern/_match.rs | 16 ++++++++++++++-- .../65413-constants-and-slices-exhaustiveness.rs | 4 ++-- ...13-constants-and-slices-exhaustiveness.stderr | 14 -------------- .../match-byte-array-patterns-2.stderr | 8 ++++---- .../usefulness/slice-patterns-exhaustiveness.rs | 2 +- .../slice-patterns-exhaustiveness.stderr | 4 ++-- 6 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 5e7a7f01e7a32..5fcaeca28a05b 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -747,7 +747,7 @@ impl<'tcx> Constructor<'tcx> { .iter() .filter_map(|c: &Constructor<'_>| match c { Slice(slice) => Some(*slice), - // FIXME(#65413): We ignore `ConstantValue`s here. + // FIXME(oli-obk): implement `deref` for `ConstValue` ConstantValue(..) => None, _ => bug!("bad slice pattern constructor {:?}", c), }) @@ -1771,7 +1771,19 @@ fn pat_constructor<'tcx>( if let Some(int_range) = IntRange::from_const(tcx, param_env, value, pat.span) { Some(IntRange(int_range)) } else { - Some(ConstantValue(value)) + match (value.val, &value.ty.kind) { + (_, ty::Array(_, n)) => { + let len = n.eval_usize(tcx, param_env); + Some(Slice(Slice { array_len: Some(len), kind: FixedLen(len) })) + } + (ty::ConstKind::Value(ConstValue::Slice { start, end, .. }), ty::Slice(_)) => { + let len = (end - start) as u64; + Some(Slice(Slice { array_len: None, kind: FixedLen(len) })) + } + // FIXME(oli-obk): implement `deref` for `ConstValue` + // (ty::ConstKind::Value(ConstValue::ByRef { .. }), ty::Slice(_)) => { ... } + _ => Some(ConstantValue(value)), + } } } PatKind::Range(PatRange { lo, hi, end }) => { diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs index cca4173e3ef1c..6c54c938bf110 100644 --- a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs +++ b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(slice_patterns)] #![deny(unreachable_patterns)] @@ -8,8 +9,7 @@ fn main() { match x { &[] => {} &[1..=255] => {} - // this shouldn't be unreachable - C0 => {} //~ unreachable pattern + C0 => {} &[_, _, ..] => {} } } diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr deleted file mode 100644 index 74421b4085c61..0000000000000 --- a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unreachable pattern - --> $DIR/65413-constants-and-slices-exhaustiveness.rs:12:9 - | -LL | C0 => {} - | ^^ - | -note: lint level defined here - --> $DIR/65413-constants-and-slices-exhaustiveness.rs:2:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr index 63ed49094fc50..539aa854f9e6b 100644 --- a/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr +++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr @@ -1,16 +1,16 @@ -error[E0004]: non-exhaustive patterns: `&[..]` not covered +error[E0004]: non-exhaustive patterns: `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered --> $DIR/match-byte-array-patterns-2.rs:4:11 | LL | match buf { - | ^^^ pattern `&[..]` not covered + | ^^^ patterns `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: `&[..]` not covered +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered --> $DIR/match-byte-array-patterns-2.rs:10:11 | LL | match buf { - | ^^^ pattern `&[..]` not covered + | ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs index 88a47fc074f5c..41ba2cc4501c0 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs +++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs @@ -97,7 +97,7 @@ fn main() { } const CONST1: &[bool; 1] = &[true]; match s1 { - //~^ ERROR `&[..]` not covered + //~^ ERROR `&[false]` not covered CONST1 => {} } match s1 { diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr index 2295de02ed532..8cb342f33dfa0 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr +++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -118,11 +118,11 @@ LL | match s { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: `&[..]` not covered +error[E0004]: non-exhaustive patterns: `&[false]` not covered --> $DIR/slice-patterns-exhaustiveness.rs:99:11 | LL | match s1 { - | ^^ pattern `&[..]` not covered + | ^^ pattern `&[false]` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms From e6e5513894ff6438a11c1805b4cc8983dada2f7d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 17 Nov 2019 23:05:50 +0000 Subject: [PATCH 3/4] Fold away `AscribeUserType` --- src/librustc_mir/hair/pattern/_match.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 5fcaeca28a05b..e1c89af186a09 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -347,6 +347,7 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> { ) => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty), (_, &PatKind::Binding { subpattern: Some(ref s), .. }) => s.fold_with(self), + (_, &PatKind::AscribeUserType { subpattern: ref s, .. }) => s.fold_with(self), _ => pat.super_fold_with(self), } } @@ -1759,9 +1760,7 @@ fn pat_constructor<'tcx>( pat: &Pat<'tcx>, ) -> Option> { match *pat.kind { - PatKind::AscribeUserType { ref subpattern, .. } => { - pat_constructor(tcx, param_env, subpattern) - } + PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern` PatKind::Binding { .. } | PatKind::Wild => None, PatKind::Leaf { .. } | PatKind::Deref { .. } => Some(Single), PatKind::Variant { adt_def, variant_index, .. } => { @@ -2262,21 +2261,17 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>( /// fields filled with wild patterns. fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>( cx: &mut MatchCheckCtxt<'a, 'tcx>, - mut pat: &'q Pat<'tcx>, + pat: &'q Pat<'tcx>, constructor: &Constructor<'tcx>, ctor_wild_subpatterns: &[&'p Pat<'tcx>], ) -> Option> { - while let PatKind::AscribeUserType { ref subpattern, .. } = *pat.kind { - pat = subpattern; - } - if let NonExhaustive = constructor { // Only a wildcard pattern can match the special extra constructor return if pat.is_wildcard() { Some(PatStack::default()) } else { None }; } let result = match *pat.kind { - PatKind::AscribeUserType { .. } => bug!(), // Handled above + PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern` PatKind::Binding { .. } | PatKind::Wild => { Some(PatStack::from_slice(ctor_wild_subpatterns)) From 3f917120a09459c649cccf903752b2addb1c9a01 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 17 Nov 2019 23:36:29 +0000 Subject: [PATCH 4/4] Reuse pat_constructor in split_grouped_ctors --- src/librustc_mir/hair/pattern/_match.rs | 37 ++++++++----------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index e1c89af186a09..5db567dae29c1 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -2096,32 +2096,19 @@ fn split_grouped_constructors<'p, 'tcx>( let mut max_suffix_len = self_suffix; let mut max_fixed_len = 0; - for row in matrix.heads() { - match *row.kind { - PatKind::Constant { value } => { - // extract the length of an array/slice from a constant - match (value.val, &value.ty.kind) { - (_, ty::Array(_, n)) => { - max_fixed_len = - cmp::max(max_fixed_len, n.eval_usize(tcx, param_env)) - } - ( - ty::ConstKind::Value(ConstValue::Slice { start, end, .. }), - ty::Slice(_), - ) => max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64), - _ => {} + let head_ctors = + matrix.heads().filter_map(|pat| pat_constructor(tcx, param_env, pat)); + for ctor in head_ctors { + match ctor { + Slice(slice) => match slice.pattern_kind() { + FixedLen(len) => { + max_fixed_len = cmp::max(max_fixed_len, len); } - } - PatKind::Slice { ref prefix, slice: None, ref suffix } - | PatKind::Array { ref prefix, slice: None, ref suffix } => { - let fixed_len = prefix.len() as u64 + suffix.len() as u64; - max_fixed_len = cmp::max(max_fixed_len, fixed_len); - } - PatKind::Slice { ref prefix, slice: Some(_), ref suffix } - | PatKind::Array { ref prefix, slice: Some(_), ref suffix } => { - max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64); - max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64); - } + VarLen(prefix, suffix) => { + max_prefix_len = cmp::max(max_prefix_len, prefix); + max_suffix_len = cmp::max(max_suffix_len, suffix); + } + }, _ => {} } }