diff options
| author | kennytm <kennytm@gmail.com> | 2018-12-14 22:10:08 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-14 22:10:08 +0800 |
| commit | 53a2de2d549f8f3af99de7c05fa8caa7aa2f2949 (patch) | |
| tree | bf765d0617f328f14106f943ca0c90125dc1fd3b | |
| parent | 35fe8c92e9b8e9d3f3b4745a6deab71d79aee4e3 (diff) | |
| parent | 510a9fffa2a03d7f4f589f3d43115f68506a657e (diff) | |
| download | rust-53a2de2d549f8f3af99de7c05fa8caa7aa2f2949.tar.gz rust-53a2de2d549f8f3af99de7c05fa8caa7aa2f2949.zip | |
Rollup merge of #56695 - varkor:let-exhaustive-range, r=estebank
Fix irrefutable matches on integer ranges Fixes https://github.com/rust-lang/rust/issues/56659.
| -rw-r--r-- | src/librustc_mir/build/matches/simplify.rs | 34 | ||||
| -rw-r--r-- | src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs | 8 |
2 files changed, 41 insertions, 1 deletions
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index cfea357334f..328b330f762 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -26,6 +26,10 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::matches::{Ascription, Binding, MatchPair, Candidate}; use hair::*; use rustc::mir::*; +use rustc::ty; +use rustc::ty::layout::{Integer, IntegerExt, Size}; +use syntax::attr::{SignedInt, UnsignedInt}; +use rustc::hir::RangeEnd; use std::mem; @@ -62,6 +66,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match_pair: MatchPair<'pat, 'tcx>, candidate: &mut Candidate<'pat, 'tcx>) -> Result<(), MatchPair<'pat, 'tcx>> { + let tcx = self.hir.tcx(); match *match_pair.pattern.kind { PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => { candidate.ascriptions.push(Ascription { @@ -104,7 +109,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Err(match_pair) } - PatternKind::Range { .. } => { + PatternKind::Range { lo, hi, ty, end } => { + let range = match ty.sty { + ty::Char => { + Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))) + } + ty::Int(ity) => { + // FIXME(49937): refactor these bit manipulations into interpret. + let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); + let min = 1u128 << (size.bits() - 1); + let max = (1u128 << (size.bits() - 1)) - 1; + Some((min, max, size)) + } + ty::Uint(uty) => { + // FIXME(49937): refactor these bit manipulations into interpret. + let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size(); + let max = !0u128 >> (128 - size.bits()); + Some((0, max, size)) + } + _ => None, + }; + if let Some((min, max, sz)) = range { + if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) { + if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) { + // Irrefutable pattern match. + return Ok(()); + } + } + } Err(match_pair) } diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs new file mode 100644 index 00000000000..ff065882d96 --- /dev/null +++ b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + let -2147483648..=2147483647 = 1; + let 0..=255 = 0u8; + let -128..=127 = 0i8; + let '\u{0000}'..='\u{10FFFF}' = 'v'; +} |
