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;
},
// 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 {
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)))
}
}
- 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),
}
}
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 { .. } |
}
}
- 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());
}
(&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 {
}
}
- (&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,
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, _) |
}
}
- (&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());
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<bool> {
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),
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<bool> {
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);
}
}
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;
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;
_ => {
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,
}
}
-> Option<IntRange<'tcx>> {
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,
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(),
) -> Result<bool, ErrorReported> {
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);
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.
},
}
+#[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 {
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, "..=")?,
);
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,
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!(
} => 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,