diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 97d983ed9e1..4d61bf8dae6 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -19,7 +19,6 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use hair::*; use hair::pattern::PatternTypeProjections; -use rustc::hir; use rustc::mir::*; use rustc::ty::{self, Ty}; use rustc::ty::layout::VariantIdx; @@ -681,12 +680,7 @@ enum TestKind<'tcx> { }, // test whether the value falls within an inclusive or exclusive range - Range { - lo: &'tcx ty::Const<'tcx>, - hi: &'tcx ty::Const<'tcx>, - ty: Ty<'tcx>, - end: hir::RangeEnd, - }, + Range(PatternRange<'tcx>), // test length of the slice is equal to len Len { diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index b9fd4f0e0b6..0ce64283870 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Err(match_pair) } - PatternKind::Range { lo, hi, ty, end } => { + PatternKind::Range(PatternRange { lo, hi, ty, end }) => { let range = match ty.sty { ty::Char => { Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))) diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 0abbfc540e6..c8dec6d0b97 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -72,16 +72,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - PatternKind::Range { lo, hi, ty, end } => { - assert!(ty == match_pair.pattern.ty); + PatternKind::Range(range) => { + assert!(range.ty == match_pair.pattern.ty); Test { span: match_pair.pattern.span, - kind: TestKind::Range { - lo, - hi, - ty, - end, - }, + kind: TestKind::Range(range), } } @@ -137,9 +132,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Variant { .. } => { panic!("you should have called add_variants_to_switch instead!"); } - PatternKind::Range { ty, lo, hi, end } => { + PatternKind::Range(range) => { // Check that none of the switch values are in the range. - self.values_not_contained_in_range(ty, lo, hi, end, indices) + self.values_not_contained_in_range(range, indices) .unwrap_or(false) } PatternKind::Slice { .. } | @@ -381,7 +376,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - TestKind::Range { ref lo, ref hi, ty, ref end } => { + TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => { // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. let lo = self.literal_operand(test.span, ty.clone(), lo.clone()); let hi = self.literal_operand(test.span, ty.clone(), hi.clone()); @@ -536,9 +531,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } (&TestKind::SwitchInt { switch_ty: _, ref options, ref indices }, - &PatternKind::Range { ty, lo, hi, end }) => { + &PatternKind::Range(range)) => { let not_contained = self - .values_not_contained_in_range(ty, lo, hi, end, indices) + .values_not_contained_in_range(range, indices) .unwrap_or(false); if not_contained { @@ -630,12 +625,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - (&TestKind::Range { - lo: test_lo, hi: test_hi, ty: test_ty, end: test_end, - }, &PatternKind::Range { - lo: pat_lo, hi: pat_hi, ty: _, end: pat_end, - }) => { - if (test_lo, test_hi, test_end) == (pat_lo, pat_hi, pat_end) { + (&TestKind::Range(test), + &PatternKind::Range(pat)) => { + if test == pat { resulting_candidates[0] .push(self.candidate_without_match_pair( match_pair_index, @@ -648,13 +640,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { use std::cmp::Ordering::*; use rustc::hir::RangeEnd::*; - let param_env = ty::ParamEnv::empty().and(test_ty); + let param_env = ty::ParamEnv::empty().and(test.ty); let tcx = self.hir.tcx(); - let lo = compare_const_vals(tcx, test_lo, pat_hi, param_env)?; - let hi = compare_const_vals(tcx, test_hi, pat_lo, param_env)?; + let lo = compare_const_vals(tcx, test.lo, pat.hi, param_env)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, param_env)?; - match (test_end, pat_end, lo, hi) { + match (test.end, pat.end, lo, hi) { // pat < test (_, _, Greater, _) | (_, Excluded, Equal, _) | @@ -675,12 +667,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - (&TestKind::Range { - lo, hi, ty, end - }, &PatternKind::Constant { - ref value - }) => { - if self.const_range_contains(ty, lo, hi, end, value) == Some(false) { + (&TestKind::Range(range), &PatternKind::Constant { ref value }) => { + if self.const_range_contains(range, value) == Some(false) { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. resulting_candidates[1].push(candidate.clone()); @@ -807,21 +795,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn const_range_contains( &self, - ty: Ty<'tcx>, - lo: &'tcx ty::Const<'tcx>, - hi: &'tcx ty::Const<'tcx>, - end: RangeEnd, + range: PatternRange<'tcx>, value: &'tcx ty::Const<'tcx>, ) -> Option { use std::cmp::Ordering::*; - let param_env = ty::ParamEnv::empty().and(ty); + let param_env = ty::ParamEnv::empty().and(range.ty); let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, lo, value, param_env)?; - let b = compare_const_vals(tcx, value, hi, param_env)?; + let a = compare_const_vals(tcx, range.lo, value, param_env)?; + let b = compare_const_vals(tcx, value, range.hi, param_env)?; - match (b, end) { + match (b, range.end) { (Less, _) | (Equal, RangeEnd::Included) if a != Greater => Some(true), _ => Some(false), @@ -830,14 +815,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn values_not_contained_in_range( &self, - ty: Ty<'tcx>, - lo: &'tcx ty::Const<'tcx>, - hi: &'tcx ty::Const<'tcx>, - end: RangeEnd, + range: PatternRange<'tcx>, indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, ) -> Option { for val in indices.keys() { - if self.const_range_contains(ty, lo, hi, end, val)? { + if self.const_range_contains(range, val)? { return Some(false); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index e604b118eac..b254fce4b76 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -29,7 +29,7 @@ pub mod cx; mod constant; pub mod pattern; -pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern}; +pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern}; pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections}; mod util; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 4c77350f10e..c0bfee803ef 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -173,7 +173,7 @@ use self::WitnessPreference::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use super::{FieldPattern, Pattern, PatternKind}; +use super::{FieldPattern, Pattern, PatternKind, PatternRange}; use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; @@ -554,12 +554,12 @@ impl<'tcx> Witness<'tcx> { _ => { match *ctor { ConstantValue(value) => PatternKind::Constant { value }, - ConstantRange(lo, hi, ty, end) => PatternKind::Range { + ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange { lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), ty, end, - }, + }), _ => PatternKind::Wild, } } @@ -820,7 +820,7 @@ impl<'tcx> IntRange<'tcx> { -> Option> { Self::from_ctor(tcx, &match pat.kind { box PatternKind::Constant { value } => ConstantValue(value), - box PatternKind::Range { lo, hi, ty, end } => ConstantRange( + box PatternKind::Range(PatternRange { lo, hi, ty, end }) => ConstantRange( lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), ty, @@ -1259,7 +1259,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Variant(adt_def.variants[variant_index].did)]) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), - PatternKind::Range { lo, hi, ty, end } => + PatternKind::Range(PatternRange { lo, hi, ty, end }) => Some(vec![ConstantRange( lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), hi.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), @@ -1556,7 +1556,7 @@ fn constructor_covered_by_range<'a, 'tcx>( ) -> Result { let (from, to, end, ty) = match pat.kind { box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), - box PatternKind::Range { lo, hi, ty, end } => (lo, hi, end, ty), + box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty), _ => bug!("`constructor_covered_by_range` called with {:?}", pat), }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 864f242a304..b014a76a739 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -219,12 +219,7 @@ pub enum PatternKind<'tcx> { value: &'tcx ty::Const<'tcx>, }, - Range { - lo: &'tcx ty::Const<'tcx>, - hi: &'tcx ty::Const<'tcx>, - ty: Ty<'tcx>, - end: RangeEnd, - }, + Range(PatternRange<'tcx>), /// matches against a slice, checking the length and extracting elements. /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. @@ -243,6 +238,14 @@ pub enum PatternKind<'tcx> { }, } +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct PatternRange<'tcx> { + pub lo: &'tcx ty::Const<'tcx>, + pub hi: &'tcx ty::Const<'tcx>, + pub ty: Ty<'tcx>, + pub end: RangeEnd, +} + impl<'tcx> fmt::Display for Pattern<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.kind { @@ -354,7 +357,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { value } => { fmt_const_val(f, value) } - PatternKind::Range { lo, hi, ty: _, end } => { + PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => { fmt_const_val(f, lo)?; match end { RangeEnd::Included => write!(f, "..=")?, @@ -483,7 +486,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => - PatternKind::Range { lo, hi, ty, end }, + PatternKind::Range(PatternRange { lo, hi, ty, end }), (RangeEnd::Excluded, _) => { span_err!( self.tcx.sess, @@ -497,7 +500,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Constant { value: lo } } (RangeEnd::Included, Some(Ordering::Less)) => { - PatternKind::Range { lo, hi, ty, end } + PatternKind::Range(PatternRange { lo, hi, ty, end }) } (RangeEnd::Included, _) => { let mut err = struct_span_err!( @@ -1177,17 +1180,17 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } => PatternKind::Constant { value: value.fold_with(folder) }, - PatternKind::Range { + PatternKind::Range(PatternRange { lo, hi, ty, end, - } => PatternKind::Range { + }) => PatternKind::Range(PatternRange { lo: lo.fold_with(folder), hi: hi.fold_with(folder), ty: ty.fold_with(folder), end, - }, + }), PatternKind::Slice { ref prefix, ref slice,