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 or the MIT license +// , 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); +}