// test for equality
Eq {
- value: Literal<'tcx>,
+ value: ConstVal,
ty: Ty<'tcx>,
},
}
}
- PatternKind::Constant { value: Literal::Value { .. } }
+ PatternKind::Constant { .. }
if is_switch_ty(match_pair.pattern.ty) => {
// for integers, we use a SwitchInt match, which allows
// us to handle more cases
}
PatternKind::Constant { ref value } => {
- // for other types, we use an equality comparison
Test {
span: match_pair.pattern.span,
kind: TestKind::Eq {
value: value.clone(),
- ty: match_pair.pattern.ty.clone(),
+ ty: match_pair.pattern.ty.clone()
}
}
}
};
match *match_pair.pattern.kind {
- PatternKind::Constant { value: Literal::Value { ref value } } => {
+ PatternKind::Constant { ref value } => {
// if the lvalues match, the type should match
assert_eq!(match_pair.pattern.ty, switch_ty);
}
PatternKind::Range { .. } |
- PatternKind::Constant { .. } |
PatternKind::Variant { .. } |
PatternKind::Slice { .. } |
PatternKind::Array { .. } |
}
TestKind::Eq { ref value, ty } => {
- // call PartialEq::eq(discrim, constant)
- let constant = self.literal_operand(test.span, ty.clone(), value.clone());
- let item_ref = self.hir.partial_eq(ty);
- self.call_comparison_fn(block, test.span, item_ref,
- Operand::Consume(lvalue.clone()), constant)
+ let expect = self.literal_operand(test.span, ty.clone(), Literal::Value {
+ value: value.clone()
+ });
+ let val = Operand::Consume(lvalue.clone());
+ let fail = self.cfg.start_new_block();
+ let block = self.compare(block, fail, test.span, BinOp::Eq, expect, val.clone());
+ vec![block, fail]
}
TestKind::Range { ref lo, ref hi, ty } => {
target_block
}
- fn call_comparison_fn(&mut self,
- block: BasicBlock,
- span: Span,
- item_ref: ItemRef<'tcx>,
- lvalue1: Operand<'tcx>,
- lvalue2: Operand<'tcx>)
- -> Vec<BasicBlock> {
- let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()];
-
- let bool_ty = self.hir.bool_ty();
- let eq_result = self.temp(bool_ty);
- let func = self.item_ref_operand(span, item_ref);
- let call_blocks = (self.cfg.start_new_block(), self.diverge_cleanup());
- self.cfg.terminate(block,
- Terminator::Call {
- data: CallData {
- destination: eq_result.clone(),
- func: func,
- args: vec![lvalue1, lvalue2],
- },
- targets: call_blocks,
- });
-
- // check the result
- self.cfg.terminate(call_blocks.0,
- Terminator::If {
- cond: Operand::Consume(eq_result),
- targets: (target_blocks[0], target_blocks[1]),
- });
-
- target_blocks
- }
-
/// Given that we are performing `test` against `test_lvalue`,
/// this job sorts out what the status of `candidate` will be
/// after the test. The `resulting_candidates` vector stores, for
// things out here, in some cases.
TestKind::SwitchInt { switch_ty: _, options: _, ref indices } => {
match *match_pair.pattern.kind {
- PatternKind::Constant { value: Literal::Value { ref value } }
+ PatternKind::Constant { ref value }
if is_switch_ty(match_pair.pattern.ty) => {
let index = indices[value];
let new_candidate = self.candidate_without_match_pair(match_pair_index,
use rustc::mir::repr::*;
use rustc::middle::const_eval::{self, ConstVal};
-use rustc::middle::def_id::DefId;
use rustc::middle::infer::InferCtxt;
-use rustc::middle::subst::{Subst, Substs};
use rustc::middle::ty::{self, Ty};
use syntax::codemap::Span;
-use syntax::parse::token;
use rustc_front::hir;
#[derive(Copy, Clone)]
.map(|v| Literal::Value { value: v })
}
- pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
- let eq_def_id = self.tcx.lang_items.eq_trait().unwrap();
- self.cmp_method_ref(eq_def_id, "eq", ty)
- }
-
pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
adt_def.variants.len()
}
pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
self.tcx
}
-
- fn cmp_method_ref(&mut self,
- trait_def_id: DefId,
- method_name: &str,
- arg_ty: Ty<'tcx>)
- -> ItemRef<'tcx> {
- let method_name = token::intern(method_name);
- let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty);
- for trait_item in self.tcx.trait_items(trait_def_id).iter() {
- match *trait_item {
- ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
- if method.name == method_name {
- let method_ty = self.tcx.lookup_item_type(method.def_id);
- let method_ty = method_ty.ty.subst(self.tcx, &substs);
- return ItemRef {
- ty: method_ty,
- kind: ItemKind::Method,
- def_id: method.def_id,
- substs: self.tcx.mk_substs(substs),
- };
- }
- }
- ty::ImplOrTraitItem::ConstTraitItem(..) |
- ty::ImplOrTraitItem::TypeTraitItem(..) => {}
- }
- }
-
- self.tcx.sess.bug(&format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
- }
}
mod block;
use rustc::middle::const_eval;
use rustc::middle::def;
use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
-use rustc::middle::subst::Substs;
use rustc::middle::ty::{self, Ty};
use rustc::mir::repr::*;
use rustc_front::hir;
use syntax::ast;
+use syntax::codemap::Span;
use syntax::ptr::P;
/// When there are multiple patterns in a single arm, each one has its
}
impl<'cx, 'tcx> Cx<'cx, 'tcx> {
- pub fn irrefutable_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
- PatCx::new(self, None).to_pat(pat)
+ pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
+ PatCx::new(self, None).to_pattern(pat)
}
pub fn refutable_pat(&mut self,
binding_map: Option<&FnvHashMap<ast::Name, ast::NodeId>>,
- pat: &'tcx hir::Pat)
+ pat: &hir::Pat)
-> Pattern<'tcx> {
- PatCx::new(self, binding_map).to_pat(pat)
+ PatCx::new(self, binding_map).to_pattern(pat)
}
}
}
}
- fn to_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
+ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
let kind = match pat.node {
hir::PatWild => PatternKind::Wild,
hir::PatLit(ref value) => {
let value = const_eval::eval_const_expr(self.cx.tcx, value);
- let value = Literal::Value { value: value };
PatternKind::Constant { value: value }
}
def::DefConst(def_id) | def::DefAssociatedConst(def_id) =>
match const_eval::lookup_const_by_id(self.cx.tcx, def_id, Some(pat.id)) {
Some(const_expr) => {
- let opt_value =
- const_eval::eval_const_expr_partial(
- self.cx.tcx, const_expr,
- const_eval::EvalHint::ExprTypeChecked,
- None);
- let literal = if let Ok(value) = opt_value {
- Literal::Value { value: value }
- } else {
- let substs = self.cx.tcx.mk_substs(Substs::empty());
- Literal::Item {
- def_id: def_id,
- kind: ItemKind::Constant,
- substs: substs
- }
- };
- PatternKind::Constant { value: literal }
+ let pat = const_eval::const_expr_to_pat(self.cx.tcx, const_expr,
+ pat.span);
+ return self.to_pattern(&*pat);
}
None => {
self.cx.tcx.sess.span_bug(
hir::PatRegion(ref subpattern, _) |
hir::PatBox(ref subpattern) => {
- PatternKind::Deref { subpattern: self.to_pat(subpattern) }
+ PatternKind::Deref { subpattern: self.to_pattern(subpattern) }
}
hir::PatVec(ref prefix, ref slice, ref suffix) => {
subpattern: Pattern {
ty: mt.ty,
span: pat.span,
- kind: Box::new(self.slice_or_array_pattern(pat, mt.ty, prefix,
+ kind: Box::new(self.slice_or_array_pattern(pat.span, mt.ty, prefix,
slice, suffix)),
},
},
ty::TySlice(..) |
ty::TyArray(..) =>
- self.slice_or_array_pattern(pat, ty, prefix, slice, suffix),
+ self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
ref sty =>
self.cx.tcx.sess.span_bug(
.enumerate()
.map(|(i, subpattern)| FieldPattern {
field: Field::new(i),
- pattern: self.to_pat(subpattern),
+ pattern: self.to_pattern(subpattern),
})
.collect();
name: ident.node.name,
var: id,
ty: var_ty,
- subpattern: self.to_opt_pat(sub),
+ subpattern: self.to_opt_pattern(sub),
}
}
.enumerate()
.map(|(i, field)| FieldPattern {
field: Field::new(i),
- pattern: self.to_pat(field),
+ pattern: self.to_pattern(field),
})
.collect();
self.variant_or_leaf(pat, subpatterns)
});
FieldPattern {
field: Field::new(index),
- pattern: self.to_pat(&field.node.pat),
+ pattern: self.to_pattern(&field.node.pat),
}
})
.collect();
}
}
- fn to_pats(&mut self, pats: &'tcx [P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
- pats.iter().map(|p| self.to_pat(p)).collect()
+ fn to_patterns(&mut self, pats: &[P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
+ pats.iter().map(|p| self.to_pattern(p)).collect()
}
- fn to_opt_pat(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pattern<'tcx>> {
- pat.as_ref().map(|p| self.to_pat(p))
+ fn to_opt_pattern(&mut self, pat: &Option<P<hir::Pat>>) -> Option<Pattern<'tcx>> {
+ pat.as_ref().map(|p| self.to_pattern(p))
}
fn slice_or_array_pattern(&mut self,
- pat: &'tcx hir::Pat,
+ span: Span,
ty: Ty<'tcx>,
- prefix: &'tcx [P<hir::Pat>],
- slice: &'tcx Option<P<hir::Pat>>,
- suffix: &'tcx [P<hir::Pat>])
+ prefix: &[P<hir::Pat>],
+ slice: &Option<P<hir::Pat>>,
+ suffix: &[P<hir::Pat>])
-> PatternKind<'tcx> {
match ty.sty {
ty::TySlice(..) => {
// matching a slice or fixed-length array
PatternKind::Slice {
- prefix: self.to_pats(prefix),
- slice: self.to_opt_pat(slice),
- suffix: self.to_pats(suffix),
+ prefix: self.to_patterns(prefix),
+ slice: self.to_opt_pattern(slice),
+ suffix: self.to_patterns(suffix),
}
}
// fixed-length array
assert!(len >= prefix.len() + suffix.len());
PatternKind::Array {
- prefix: self.to_pats(prefix),
- slice: self.to_opt_pat(slice),
- suffix: self.to_pats(suffix),
+ prefix: self.to_patterns(prefix),
+ slice: self.to_opt_pattern(slice),
+ suffix: self.to_patterns(suffix),
}
}
_ => {
- self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc");
+ self.cx.tcx.sess.span_bug(span, "unexpanded macro or bad constant etc");
}
}
}
fn variant_or_leaf(&mut self,
- pat: &'tcx hir::Pat,
+ pat: &hir::Pat,
subpatterns: Vec<FieldPattern<'tcx>>)
-> PatternKind<'tcx> {
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
//! structures.
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind};
+use rustc::middle::const_eval::ConstVal;
use rustc::middle::def_id::DefId;
use rustc::middle::region::CodeExtent;
use rustc::middle::subst::Substs;
}, // box P, &P, &mut P, etc
Constant {
- value: Literal<'tcx>,
+ value: ConstVal,
},
Range {
--- /dev/null
+// 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 test1(x: i8) -> i32 {
+ match x {
+ 1...10 => 0,
+ _ => 1,
+ }
+}
+
+const U: Option<i8> = Some(10);
+const S: &'static str = "hello";
+
+#[rustc_mir]
+pub fn test2(x: i8) -> i32 {
+ match Some(x) {
+ U => 0,
+ _ => 1,
+ }
+}
+
+#[rustc_mir]
+pub fn test3(x: &'static str) -> i32 {
+ match x {
+ S => 0,
+ _ => 1,
+ }
+}
+
+fn main() {
+ assert_eq!(test1(0), 1);
+ assert_eq!(test1(1), 0);
+ assert_eq!(test1(2), 0);
+ assert_eq!(test1(5), 0);
+ assert_eq!(test1(9), 0);
+ assert_eq!(test1(10), 0);
+ assert_eq!(test1(11), 1);
+ assert_eq!(test1(20), 1);
+ assert_eq!(test2(10), 0);
+ assert_eq!(test2(0), 1);
+ assert_eq!(test2(20), 1);
+ assert_eq!(test3("hello"), 0);
+ assert_eq!(test3(""), 1);
+ assert_eq!(test3("world"), 1);
+}
+++ /dev/null
-// 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);
-}