about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-12-31 09:40:02 +0000
committerbors <bors@rust-lang.org>2015-12-31 09:40:02 +0000
commit7f3201d13108f411cf574a77b732f422245e3fe0 (patch)
tree2046794916b3d4eeb68bc877282040902b714002
parentf73c0a82ecd28feab1c7328d8659f6d75bd60679 (diff)
parent78526fcfd18ed65cc61af21fc2687174563aec8b (diff)
downloadrust-7f3201d13108f411cf574a77b732f422245e3fe0.tar.gz
rust-7f3201d13108f411cf574a77b732f422245e3fe0.zip
Auto merge of #30641 - tsion:match-range, r=eddyb
The previous version using `PartialOrd::le` was broken since it passed `T` arguments where `&T` was expected.

It makes sense to use primitive comparisons since range patterns can only be used with chars and numeric types.

r? @eddyb
-rw-r--r--src/librustc_mir/build/matches/test.rs47
-rw-r--r--src/librustc_mir/hair/cx/mod.rs5
-rw-r--r--src/test/run-pass/mir_trans_match_range.rs30
3 files changed, 59 insertions, 23 deletions
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 7b329fc4d52..7591e80e85f 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -185,28 +185,16 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             }
 
             TestKind::Range { ref lo, ref hi, ty } => {
-                // Test `v` by computing `PartialOrd::le(lo, v) && PartialOrd::le(v, hi)`.
+                // 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());
-                let item_ref = self.hir.partial_le(ty);
+                let val = Operand::Consume(lvalue.clone());
 
-                let lo_blocks = self.call_comparison_fn(block,
-                                                        test.span,
-                                                        item_ref.clone(),
-                                                        lo,
-                                                        Operand::Consume(lvalue.clone()));
+                let fail = self.cfg.start_new_block();
+                let block = self.compare(block, fail, test.span, BinOp::Le, lo, val.clone());
+                let block = self.compare(block, fail, test.span, BinOp::Le, val, hi);
 
-                let hi_blocks = self.call_comparison_fn(lo_blocks[0],
-                                                        test.span,
-                                                        item_ref,
-                                                        Operand::Consume(lvalue.clone()),
-                                                        hi);
-
-                let failure = self.cfg.start_new_block();
-                self.cfg.terminate(lo_blocks[1], Terminator::Goto { target: failure });
-                self.cfg.terminate(hi_blocks[1], Terminator::Goto { target: failure });
-
-                vec![hi_blocks[0], failure]
+                vec![block, fail]
             }
 
             TestKind::Len { len, op } => {
@@ -240,6 +228,29 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         }
     }
 
+    fn compare(&mut self,
+               block: BasicBlock,
+               fail_block: BasicBlock,
+               span: Span,
+               op: BinOp,
+               left: Operand<'tcx>,
+               right: Operand<'tcx>) -> BasicBlock {
+        let bool_ty = self.hir.bool_ty();
+        let result = self.temp(bool_ty);
+
+        // result = op(left, right)
+        self.cfg.push_assign(block, span, &result, Rvalue::BinaryOp(op, left, right));
+
+        // branch based on result
+        let target_block = self.cfg.start_new_block();
+        self.cfg.terminate(block, Terminator::If {
+            cond: Operand::Consume(result),
+            targets: (target_block, fail_block)
+        });
+
+        target_block
+    }
+
     fn call_comparison_fn(&mut self,
                           block: BasicBlock,
                           span: Span,
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index d6cfd1a2c6e..d24d0985355 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -88,11 +88,6 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
         self.cmp_method_ref(eq_def_id, "eq", ty)
     }
 
-    pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
-        let ord_def_id = self.tcx.lang_items.ord_trait().unwrap();
-        self.cmp_method_ref(ord_def_id, "le", ty)
-    }
-
     pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
         adt_def.variants.len()
     }
diff --git a/src/test/run-pass/mir_trans_match_range.rs b/src/test/run-pass/mir_trans_match_range.rs
new file mode 100644
index 00000000000..14184bd356b
--- /dev/null
+++ b/src/test/run-pass/mir_trans_match_range.rs
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+#[rustc_mir]
+pub fn foo(x: i8) -> i32 {
+  match x {
+    1...10 => 0,
+    _ => 1,
+  }
+}
+
+fn main() {
+  assert_eq!(foo(0), 1);
+  assert_eq!(foo(1), 0);
+  assert_eq!(foo(2), 0);
+  assert_eq!(foo(5), 0);
+  assert_eq!(foo(9), 0);
+  assert_eq!(foo(10), 0);
+  assert_eq!(foo(11), 1);
+  assert_eq!(foo(20), 1);
+}