about summary refs log tree commit diff
path: root/src/librustc_const_eval
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-01-25 02:17:33 +0000
committerbors <bors@rust-lang.org>2017-01-25 02:17:33 +0000
commitc0d0e68be4f8bb9d8522bd72a7a1b8ef95b84c6c (patch)
tree2df7197e1d4cbf264e68bf7e9ce2df67b60f574a /src/librustc_const_eval
parent83c2d95238e3545e7ae9af4873c48b1e3651c164 (diff)
parent98fef41d63a91759790f5bbe4ac746b5c1a670ba (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.rs51
-rw-r--r--src/librustc_const_eval/pattern.rs20
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,