1
Fork 0

Add common struct for range

This commit is contained in:
Shotaro Yamada 2018-12-15 23:04:23 +09:00
parent 2c1b1c26f4
commit 059bbd962e
6 changed files with 48 additions and 69 deletions

View file

@ -19,7 +19,6 @@ use build::{BlockAnd, BlockAndExtension, Builder};
use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
use hair::*; use hair::*;
use hair::pattern::PatternTypeProjections; use hair::pattern::PatternTypeProjections;
use rustc::hir;
use rustc::mir::*; use rustc::mir::*;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::ty::layout::VariantIdx; use rustc::ty::layout::VariantIdx;
@ -681,12 +680,7 @@ enum TestKind<'tcx> {
}, },
// test whether the value falls within an inclusive or exclusive range // test whether the value falls within an inclusive or exclusive range
Range { Range(PatternRange<'tcx>),
lo: &'tcx ty::Const<'tcx>,
hi: &'tcx ty::Const<'tcx>,
ty: Ty<'tcx>,
end: hir::RangeEnd,
},
// test length of the slice is equal to len // test length of the slice is equal to len
Len { Len {

View file

@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Err(match_pair) Err(match_pair)
} }
PatternKind::Range { lo, hi, ty, end } => { PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
let range = match ty.sty { let range = match ty.sty {
ty::Char => { ty::Char => {
Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))) Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))

View file

@ -72,16 +72,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
} }
} }
PatternKind::Range { lo, hi, ty, end } => { PatternKind::Range(range) => {
assert!(ty == match_pair.pattern.ty); assert!(range.ty == match_pair.pattern.ty);
Test { Test {
span: match_pair.pattern.span, span: match_pair.pattern.span,
kind: TestKind::Range { kind: TestKind::Range(range),
lo,
hi,
ty,
end,
},
} }
} }
@ -137,9 +132,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
PatternKind::Variant { .. } => { PatternKind::Variant { .. } => {
panic!("you should have called add_variants_to_switch instead!"); 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. // 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) .unwrap_or(false)
} }
PatternKind::Slice { .. } | 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. // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
let lo = self.literal_operand(test.span, ty.clone(), lo.clone()); let lo = self.literal_operand(test.span, ty.clone(), lo.clone());
let hi = self.literal_operand(test.span, ty.clone(), hi.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 }, (&TestKind::SwitchInt { switch_ty: _, ref options, ref indices },
&PatternKind::Range { ty, lo, hi, end }) => { &PatternKind::Range(range)) => {
let not_contained = self let not_contained = self
.values_not_contained_in_range(ty, lo, hi, end, indices) .values_not_contained_in_range(range, indices)
.unwrap_or(false); .unwrap_or(false);
if not_contained { if not_contained {
@ -630,12 +625,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
} }
} }
(&TestKind::Range { (&TestKind::Range(test),
lo: test_lo, hi: test_hi, ty: test_ty, end: test_end, &PatternKind::Range(pat)) => {
}, &PatternKind::Range { if test == pat {
lo: pat_lo, hi: pat_hi, ty: _, end: pat_end,
}) => {
if (test_lo, test_hi, test_end) == (pat_lo, pat_hi, pat_end) {
resulting_candidates[0] resulting_candidates[0]
.push(self.candidate_without_match_pair( .push(self.candidate_without_match_pair(
match_pair_index, match_pair_index,
@ -648,13 +640,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
use std::cmp::Ordering::*; use std::cmp::Ordering::*;
use rustc::hir::RangeEnd::*; 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 tcx = self.hir.tcx();
let lo = compare_const_vals(tcx, test_lo, pat_hi, 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)?; 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 // pat < test
(_, _, Greater, _) | (_, _, Greater, _) |
(_, Excluded, Equal, _) | (_, Excluded, Equal, _) |
@ -675,12 +667,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
} }
} }
(&TestKind::Range { (&TestKind::Range(range), &PatternKind::Constant { ref value }) => {
lo, hi, ty, end if self.const_range_contains(range, value) == Some(false) {
}, &PatternKind::Constant {
ref value
}) => {
if self.const_range_contains(ty, lo, hi, end, value) == Some(false) {
// `value` is not contained in the testing range, // `value` is not contained in the testing range,
// so `value` can be matched only if this test fails. // so `value` can be matched only if this test fails.
resulting_candidates[1].push(candidate.clone()); resulting_candidates[1].push(candidate.clone());
@ -807,21 +795,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
fn const_range_contains( fn const_range_contains(
&self, &self,
ty: Ty<'tcx>, range: PatternRange<'tcx>,
lo: &'tcx ty::Const<'tcx>,
hi: &'tcx ty::Const<'tcx>,
end: RangeEnd,
value: &'tcx ty::Const<'tcx>, value: &'tcx ty::Const<'tcx>,
) -> Option<bool> { ) -> Option<bool> {
use std::cmp::Ordering::*; 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 tcx = self.hir.tcx();
let a = compare_const_vals(tcx, lo, value, param_env)?; let a = compare_const_vals(tcx, range.lo, value, param_env)?;
let b = compare_const_vals(tcx, value, hi, param_env)?; let b = compare_const_vals(tcx, value, range.hi, param_env)?;
match (b, end) { match (b, range.end) {
(Less, _) | (Less, _) |
(Equal, RangeEnd::Included) if a != Greater => Some(true), (Equal, RangeEnd::Included) if a != Greater => Some(true),
_ => Some(false), _ => Some(false),
@ -830,14 +815,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
fn values_not_contained_in_range( fn values_not_contained_in_range(
&self, &self,
ty: Ty<'tcx>, range: PatternRange<'tcx>,
lo: &'tcx ty::Const<'tcx>,
hi: &'tcx ty::Const<'tcx>,
end: RangeEnd,
indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>,
) -> Option<bool> { ) -> Option<bool> {
for val in indices.keys() { 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); return Some(false);
} }
} }

View file

@ -29,7 +29,7 @@ pub mod cx;
mod constant; mod constant;
pub mod pattern; 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}; pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
mod util; mod util;

View file

@ -173,7 +173,7 @@ use self::WitnessPreference::*;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx; 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 super::{PatternFoldable, PatternFolder, compare_const_vals};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
@ -554,12 +554,12 @@ impl<'tcx> Witness<'tcx> {
_ => { _ => {
match *ctor { match *ctor {
ConstantValue(value) => PatternKind::Constant { value }, 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)), 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)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
ty, ty,
end, end,
}, }),
_ => PatternKind::Wild, _ => PatternKind::Wild,
} }
} }
@ -820,7 +820,7 @@ impl<'tcx> IntRange<'tcx> {
-> Option<IntRange<'tcx>> { -> Option<IntRange<'tcx>> {
Self::from_ctor(tcx, &match pat.kind { Self::from_ctor(tcx, &match pat.kind {
box PatternKind::Constant { value } => ConstantValue(value), 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(), lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
ty, ty,
@ -1259,7 +1259,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
Some(vec![Variant(adt_def.variants[variant_index].did)]) Some(vec![Variant(adt_def.variants[variant_index].did)])
} }
PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
PatternKind::Range { lo, hi, ty, end } => PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
Some(vec![ConstantRange( Some(vec![ConstantRange(
lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(),
hi.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<bool, ErrorReported> { ) -> Result<bool, ErrorReported> {
let (from, to, end, ty) = match pat.kind { let (from, to, end, ty) = match pat.kind {
box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), 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), _ => bug!("`constructor_covered_by_range` called with {:?}", pat),
}; };
trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);

View file

@ -219,12 +219,7 @@ pub enum PatternKind<'tcx> {
value: &'tcx ty::Const<'tcx>, value: &'tcx ty::Const<'tcx>,
}, },
Range { Range(PatternRange<'tcx>),
lo: &'tcx ty::Const<'tcx>,
hi: &'tcx ty::Const<'tcx>,
ty: Ty<'tcx>,
end: RangeEnd,
},
/// matches against a slice, checking the length and extracting elements. /// matches against a slice, checking the length and extracting elements.
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. /// 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> { impl<'tcx> fmt::Display for Pattern<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.kind { match *self.kind {
@ -354,7 +357,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
PatternKind::Constant { value } => { PatternKind::Constant { value } => {
fmt_const_val(f, value) fmt_const_val(f, value)
} }
PatternKind::Range { lo, hi, ty: _, end } => { PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
fmt_const_val(f, lo)?; fmt_const_val(f, lo)?;
match end { match end {
RangeEnd::Included => write!(f, "..=")?, RangeEnd::Included => write!(f, "..=")?,
@ -483,7 +486,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
); );
match (end, cmp) { match (end, cmp) {
(RangeEnd::Excluded, Some(Ordering::Less)) => (RangeEnd::Excluded, Some(Ordering::Less)) =>
PatternKind::Range { lo, hi, ty, end }, PatternKind::Range(PatternRange { lo, hi, ty, end }),
(RangeEnd::Excluded, _) => { (RangeEnd::Excluded, _) => {
span_err!( span_err!(
self.tcx.sess, self.tcx.sess,
@ -497,7 +500,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
PatternKind::Constant { value: lo } PatternKind::Constant { value: lo }
} }
(RangeEnd::Included, Some(Ordering::Less)) => { (RangeEnd::Included, Some(Ordering::Less)) => {
PatternKind::Range { lo, hi, ty, end } PatternKind::Range(PatternRange { lo, hi, ty, end })
} }
(RangeEnd::Included, _) => { (RangeEnd::Included, _) => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -1177,17 +1180,17 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
} => PatternKind::Constant { } => PatternKind::Constant {
value: value.fold_with(folder) value: value.fold_with(folder)
}, },
PatternKind::Range { PatternKind::Range(PatternRange {
lo, lo,
hi, hi,
ty, ty,
end, end,
} => PatternKind::Range { }) => PatternKind::Range(PatternRange {
lo: lo.fold_with(folder), lo: lo.fold_with(folder),
hi: hi.fold_with(folder), hi: hi.fold_with(folder),
ty: ty.fold_with(folder), ty: ty.fold_with(folder),
end, end,
}, }),
PatternKind::Slice { PatternKind::Slice {
ref prefix, ref prefix,
ref slice, ref slice,