mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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
This commit is contained in:
commit
7f3201d131
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
|
30
src/test/run-pass/mir_trans_match_range.rs
Normal file
30
src/test/run-pass/mir_trans_match_range.rs
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user