Add common struct for range
This commit is contained in:
parent
2c1b1c26f4
commit
059bbd962e
6 changed files with 48 additions and 69 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue