diff options
| author | bors <bors@rust-lang.org> | 2017-01-25 02:17:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-01-25 02:17:33 +0000 |
| commit | c0d0e68be4f8bb9d8522bd72a7a1b8ef95b84c6c (patch) | |
| tree | 2df7197e1d4cbf264e68bf7e9ce2df67b60f574a /src/librustc_const_eval | |
| parent | 83c2d95238e3545e7ae9af4873c48b1e3651c164 (diff) | |
| parent | 98fef41d63a91759790f5bbe4ac746b5c1a670ba (diff) | |
Auto merge of #35712 - oli-obk:exclusive_range_patterns, r=nikomatsakis
exclusive range patterns
adds `..` patterns to the language under a feature gate (`exclusive_range_pattern`).
This allows turning
``` rust
match i {
0...9 => {},
10...19 => {},
20...29 => {},
_ => {}
}
```
into
``` rust
match i {
0..10 => {},
10..20 => {},
20..30 => {},
_ => {}
}
```
Diffstat (limited to 'src/librustc_const_eval')
| -rw-r--r-- | src/librustc_const_eval/_match.rs | 51 | ||||
| -rw-r--r-- | src/librustc_const_eval/pattern.rs | 20 |
2 files changed, 47 insertions, 24 deletions
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index f4b3646fce0..bb5dacf71e1 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -24,6 +24,7 @@ use pattern::{FieldPattern, Pattern, PatternKind}; use pattern::{PatternFoldable, PatternFolder}; use rustc::hir::def_id::DefId; +use rustc::hir::RangeEnd; use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable}; use rustc::mir::Field; @@ -206,8 +207,8 @@ pub enum Constructor { Variant(DefId), /// Literal values. ConstantValue(ConstVal), - /// Ranges of literal values (2..5). - ConstantRange(ConstVal, ConstVal), + /// Ranges of literal values (`2...5` and `2..5`). + ConstantRange(ConstVal, ConstVal, RangeEnd), /// Array patterns of length n. Slice(usize), } @@ -686,8 +687,8 @@ fn pat_constructors(_cx: &mut MatchCheckCtxt, Some(vec![Variant(adt_def.variants[variant_index].did)]), PatternKind::Constant { ref value } => Some(vec![ConstantValue(value.clone())]), - PatternKind::Range { ref lo, ref hi } => - Some(vec![ConstantRange(lo.clone(), hi.clone())]), + PatternKind::Range { ref lo, ref hi, ref end } => + Some(vec![ConstantRange(lo.clone(), hi.clone(), end.clone())]), PatternKind::Array { .. } => match pcx.ty.sty { ty::TyArray(_, length) => Some(vec![Slice(length)]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) @@ -791,17 +792,33 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span, fn range_covered_by_constructor(tcx: TyCtxt, span: Span, ctor: &Constructor, - from: &ConstVal, to: &ConstVal) + from: &ConstVal, to: &ConstVal, + end: RangeEnd) -> Result<bool, ErrorReported> { - let (c_from, c_to) = match *ctor { - ConstantValue(ref value) => (value, value), - ConstantRange(ref from, ref to) => (from, to), - Single => return Ok(true), - _ => bug!() - }; - let cmp_from = compare_const_vals(tcx, span, c_from, from)?; - let cmp_to = compare_const_vals(tcx, span, c_to, to)?; - Ok(cmp_from != Ordering::Less && cmp_to != Ordering::Greater) + let cmp_from = |c_from| Ok(compare_const_vals(tcx, span, c_from, from)? != Ordering::Less); + let cmp_to = |c_to| compare_const_vals(tcx, span, c_to, to); + match *ctor { + ConstantValue(ref value) => { + let to = cmp_to(value)?; + let end = (to != Ordering::Greater) || + (end == RangeEnd::Excluded && to == Ordering::Equal); + Ok(cmp_from(value)? && end) + }, + ConstantRange(ref from, ref to, RangeEnd::Included) => { + let to = cmp_to(to)?; + let end = (to != Ordering::Greater) || + (end == RangeEnd::Excluded && to == Ordering::Equal); + Ok(cmp_from(from)? && end) + }, + ConstantRange(ref from, ref to, RangeEnd::Excluded) => { + let to = cmp_to(to)?; + let end = (to == Ordering::Less) || + (end == RangeEnd::Excluded && to == Ordering::Equal); + Ok(cmp_from(from)? && end) + } + Single => Ok(true), + _ => bug!(), + } } fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>( @@ -872,7 +889,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( }, _ => { match range_covered_by_constructor( - cx.tcx, pat.span, constructor, value, value + cx.tcx, pat.span, constructor, value, value, RangeEnd::Included ) { Ok(true) => Some(vec![]), Ok(false) => None, @@ -882,9 +899,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( } } - PatternKind::Range { ref lo, ref hi } => { + PatternKind::Range { ref lo, ref hi, ref end } => { match range_covered_by_constructor( - cx.tcx, pat.span, constructor, lo, hi + cx.tcx, pat.span, constructor, lo, hi, end.clone() ) { Ok(true) => Some(vec![]), Ok(false) => None, diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index fbd15b6eb10..3235e06b806 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -15,7 +15,7 @@ use rustc::middle::const_val::ConstVal; use rustc::mir::{Field, BorrowKind, Mutability}; use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; use rustc::ty::subst::{Substs, Kind}; -use rustc::hir::{self, PatKind}; +use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; @@ -90,6 +90,7 @@ pub enum PatternKind<'tcx> { Range { lo: ConstVal, hi: ConstVal, + end: RangeEnd, }, /// matches against a slice, checking the length and extracting elements @@ -228,9 +229,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { ref value } => { print_const_val(value, f) } - PatternKind::Range { ref lo, ref hi } => { + PatternKind::Range { ref lo, ref hi, ref end } => { print_const_val(lo, f)?; - write!(f, "...")?; + match *end { + RangeEnd::Included => write!(f, "...")?, + RangeEnd::Excluded => write!(f, "..")?, + } print_const_val(hi, f) } PatternKind::Slice { ref prefix, ref slice, ref suffix } | @@ -291,11 +295,11 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Lit(ref value) => self.lower_lit(value), - PatKind::Range(ref lo, ref hi) => { + PatKind::Range(ref lo, ref hi, ref end) => { match (self.lower_lit(lo), self.lower_lit(hi)) { (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { - PatternKind::Range { lo: lo, hi: hi } + PatternKind::Range { lo: lo, hi: hi, end: end.clone() } } _ => PatternKind::Wild } @@ -871,10 +875,12 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { }, PatternKind::Range { ref lo, - ref hi + ref hi, + ref end, } => PatternKind::Range { lo: lo.fold_with(folder), - hi: hi.fold_with(folder) + hi: hi.fold_with(folder), + end: end.clone(), }, PatternKind::Slice { ref prefix, |
