diff options
| author | Scott Olson <scott@solson.me> | 2015-12-30 10:25:35 -0600 |
|---|---|---|
| committer | Scott Olson <scott@solson.me> | 2015-12-30 10:25:41 -0600 |
| commit | 8a834097cc179a4f5cd685230b92772d371c920f (patch) | |
| tree | dcf9a3377f2b24fab310d07508559856b23c16d0 | |
| parent | 6e2a64b57a74f35bef215972adf1b803cff288bd (diff) | |
Use built-in comparisons for range matching in MIR.
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.
| -rw-r--r-- | src/librustc_mir/build/matches/test.rs | 47 | ||||
| -rw-r--r-- | src/librustc_mir/hair/cx/mod.rs | 5 |
2 files changed, 29 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() } |
