diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index e72d903756a1..ff4e440205a1 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -44,7 +44,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { // be unreachable or reachable multiple times. let var_extent = self.extent_of_innermost_scope().unwrap(); for arm in &arms { - self.declare_bindings(var_extent, arm.patterns[0].clone()); + self.declare_bindings(var_extent, &arm.patterns[0]); } let mut arm_blocks = ArmBlocks { @@ -64,18 +64,18 @@ impl<'a,'tcx> Builder<'a,'tcx> { // highest priority candidate comes last in the list. This the // reverse of the order in which candidates are written in the // source. - let candidates: Vec> = + let candidates: Vec<_> = arms.iter() .enumerate() .rev() // highest priority comes last .flat_map(|(arm_index, arm)| { arm.patterns.iter() .rev() - .map(move |pat| (arm_index, pat.clone(), arm.guard.clone())) + .map(move |pat| (arm_index, pat, arm.guard.clone())) }) .map(|(arm_index, pattern, guard)| { Candidate { - match_pairs: vec![self.match_pair(discriminant_lvalue.clone(), pattern)], + match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)], bindings: vec![], guard: guard, arm_index: arm_index, @@ -102,12 +102,11 @@ impl<'a,'tcx> Builder<'a,'tcx> { pub fn expr_into_pattern(&mut self, mut block: BasicBlock, var_extent: CodeExtent, // lifetime of vars - irrefutable_pat: PatternRef<'tcx>, + irrefutable_pat: Pattern<'tcx>, initializer: ExprRef<'tcx>) -> BlockAnd<()> { // optimize the case of `let x = ...` - let irrefutable_pat = self.hir.mirror(irrefutable_pat); - match irrefutable_pat.kind { + match *irrefutable_pat.kind { PatternKind::Binding { mutability, name, mode: BindingMode::ByValue, @@ -128,22 +127,22 @@ impl<'a,'tcx> Builder<'a,'tcx> { let lvalue = unpack!(block = self.as_lvalue(block, initializer)); self.lvalue_into_pattern(block, var_extent, - PatternRef::Mirror(Box::new(irrefutable_pat)), + irrefutable_pat, &lvalue) } pub fn lvalue_into_pattern(&mut self, mut block: BasicBlock, var_extent: CodeExtent, - irrefutable_pat: PatternRef<'tcx>, + irrefutable_pat: Pattern<'tcx>, initializer: &Lvalue<'tcx>) -> BlockAnd<()> { // first, creating the bindings - self.declare_bindings(var_extent, irrefutable_pat.clone()); + self.declare_bindings(var_extent, &irrefutable_pat); // create a dummy candidate - let mut candidate = Candidate::<'tcx> { - match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())], + let mut candidate = Candidate { + match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)], bindings: vec![], guard: None, arm_index: 0, // since we don't call `match_candidates`, this field is unused @@ -166,29 +165,29 @@ impl<'a,'tcx> Builder<'a,'tcx> { block.unit() } - pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: PatternRef<'tcx>) { - let pattern = self.hir.mirror(pattern); - match pattern.kind { - PatternKind::Binding { mutability, name, mode: _, var, ty, subpattern } => { + pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: &Pattern<'tcx>) { + match *pattern.kind { + PatternKind::Binding { mutability, name, mode: _, var, ty, ref subpattern } => { self.declare_binding(var_extent, mutability, name, var, ty, pattern.span); - if let Some(subpattern) = subpattern { + if let Some(subpattern) = subpattern.as_ref() { self.declare_bindings(var_extent, subpattern); } } - PatternKind::Array { prefix, slice, suffix } | - PatternKind::Slice { prefix, slice, suffix } => { - for subpattern in prefix.into_iter().chain(slice).chain(suffix) { + PatternKind::Array { ref prefix, ref slice, ref suffix } | + PatternKind::Slice { ref prefix, ref slice, ref suffix } => { + for subpattern in prefix.iter().chain(slice).chain(suffix) { self.declare_bindings(var_extent, subpattern); } } - PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {} - PatternKind::Deref { subpattern } => { + PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => { + } + PatternKind::Deref { ref subpattern } => { self.declare_bindings(var_extent, subpattern); } - PatternKind::Leaf { subpatterns } | - PatternKind::Variant { subpatterns, .. } => { + PatternKind::Leaf { ref subpatterns } | + PatternKind::Variant { ref subpatterns, .. } => { for subpattern in subpatterns { - self.declare_bindings(var_extent, subpattern.pattern); + self.declare_bindings(var_extent, &subpattern.pattern); } } } @@ -202,9 +201,9 @@ struct ArmBlocks { } #[derive(Clone, Debug)] -struct Candidate<'tcx> { +struct Candidate<'pat, 'tcx:'pat> { // all of these must be satisfied... - match_pairs: Vec>, + match_pairs: Vec>, // ...these bindings established... bindings: Vec>, @@ -228,12 +227,12 @@ struct Binding<'tcx> { } #[derive(Clone, Debug)] -struct MatchPair<'tcx> { +struct MatchPair<'pat, 'tcx:'pat> { // this lvalue... lvalue: Lvalue<'tcx>, // ... must match this pattern. - pattern: Pattern<'tcx>, + pattern: &'pat Pattern<'tcx>, } #[derive(Clone, Debug, PartialEq)] @@ -280,11 +279,11 @@ struct Test<'tcx> { // Main matching algorithm impl<'a,'tcx> Builder<'a,'tcx> { - fn match_candidates(&mut self, - span: Span, - arm_blocks: &mut ArmBlocks, - mut candidates: Vec>, - mut block: BasicBlock) + fn match_candidates<'pat>(&mut self, + span: Span, + arm_blocks: &mut ArmBlocks, + mut candidates: Vec>, + mut block: BasicBlock) { debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})", span, block, candidates); @@ -347,7 +346,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { let target_blocks = self.perform_test(block, &match_pair.lvalue, &test); for (outcome, target_block) in target_blocks.into_iter().enumerate() { - let applicable_candidates: Vec> = + let applicable_candidates: Vec<_> = candidates.iter() .filter_map(|candidate| { self.candidate_under_assumption(&match_pair.lvalue, @@ -372,11 +371,11 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// bindings, further tests would be a use-after-move (which would /// in turn be detected by the borrowck code that runs on the /// MIR). - fn bind_and_guard_matched_candidate(&mut self, - mut block: BasicBlock, - arm_blocks: &mut ArmBlocks, - candidate: Candidate<'tcx>) - -> Option { + fn bind_and_guard_matched_candidate<'pat>(&mut self, + mut block: BasicBlock, + arm_blocks: &mut ArmBlocks, + candidate: Candidate<'pat, 'tcx>) + -> Option { debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})", block, candidate); diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 0267e9b10cec..e69a04322c20 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -30,10 +30,10 @@ use repr::*; use std::mem; impl<'a,'tcx> Builder<'a,'tcx> { - pub fn simplify_candidate(&mut self, - mut block: BasicBlock, - candidate: &mut Candidate<'tcx>) - -> BlockAnd<()> { + pub fn simplify_candidate<'pat>(&mut self, + mut block: BasicBlock, + candidate: &mut Candidate<'pat, 'tcx>) + -> BlockAnd<()> { // repeatedly simplify match pairs until fixed point is reached loop { let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]); @@ -60,18 +60,18 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// have been pushed into the candidate. If no simplification is /// possible, Err is returned and no changes are made to /// candidate. - fn simplify_match_pair(&mut self, - mut block: BasicBlock, - match_pair: MatchPair<'tcx>, - candidate: &mut Candidate<'tcx>) - -> Result> { - match match_pair.pattern.kind { + fn simplify_match_pair<'pat>(&mut self, + mut block: BasicBlock, + match_pair: MatchPair<'pat, 'tcx>, + candidate: &mut Candidate<'pat, 'tcx>) + -> Result> { + match *match_pair.pattern.kind { PatternKind::Wild(..) => { // nothing left to do Ok(block) } - PatternKind::Binding { name, mutability, mode, var, ty, subpattern } => { + PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => { candidate.bindings.push(Binding { name: name, mutability: mutability, @@ -82,9 +82,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { binding_mode: mode, }); - if let Some(subpattern) = subpattern { + if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now - let subpattern = self.hir.mirror(subpattern); candidate.match_pairs.push(MatchPair::new(match_pair.lvalue, subpattern)); } @@ -96,12 +95,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { Err(match_pair) } - PatternKind::Array { prefix, slice, suffix } => { + PatternKind::Array { ref prefix, ref slice, ref suffix } => { unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs, block, match_pair.lvalue.clone(), prefix, - slice, + slice.as_ref(), suffix)); Ok(block) } @@ -113,16 +112,15 @@ impl<'a,'tcx> Builder<'a,'tcx> { Err(match_pair) } - PatternKind::Leaf { subpatterns } => { + PatternKind::Leaf { ref subpatterns } => { // tuple struct, match subpats (if any) candidate.match_pairs .extend(self.field_match_pairs(match_pair.lvalue, subpatterns)); Ok(block) } - PatternKind::Deref { subpattern } => { + PatternKind::Deref { ref subpattern } => { let lvalue = match_pair.lvalue.deref(); - let subpattern = self.hir.mirror(subpattern); candidate.match_pairs.push(MatchPair::new(lvalue, subpattern)); Ok(block) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 280b5f1d67ff..70d70bade21c 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -28,8 +28,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a simplifyable pattern. - pub fn test(&mut self, match_pair: &MatchPair<'tcx>) -> Test<'tcx> { - match match_pair.pattern.kind { + pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { + match *match_pair.pattern.kind { PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => { Test { span: match_pair.pattern.span, @@ -99,19 +99,19 @@ impl<'a,'tcx> Builder<'a,'tcx> { } } - pub fn add_cases_to_switch(&mut self, - test_lvalue: &Lvalue<'tcx>, - candidate: &Candidate<'tcx>, - switch_ty: Ty<'tcx>, - options: &mut Vec, - indices: &mut FnvHashMap) + pub fn add_cases_to_switch<'pat>(&mut self, + test_lvalue: &Lvalue<'tcx>, + candidate: &Candidate<'pat, 'tcx>, + switch_ty: Ty<'tcx>, + options: &mut Vec, + indices: &mut FnvHashMap) { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) { Some(match_pair) => match_pair, _ => { return; } }; - match match_pair.pattern.kind { + match *match_pair.pattern.kind { PatternKind::Constant { value: Literal::Value { ref value } } => { // if the lvalues match, the type should match assert_eq!(match_pair.pattern.ty, switch_ty); @@ -282,12 +282,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// parameter), we would return `None`. But if the test_outcome /// were `Ok`, we would return `Some([x.0.downcast.0 @ P1, x.1 /// @ 22])`. - pub fn candidate_under_assumption(&mut self, - test_lvalue: &Lvalue<'tcx>, - test_kind: &TestKind<'tcx>, - test_outcome: usize, - candidate: &Candidate<'tcx>) - -> Option> { + pub fn candidate_under_assumption<'pat>(&mut self, + test_lvalue: &Lvalue<'tcx>, + test_kind: &TestKind<'tcx>, + test_outcome: usize, + candidate: &Candidate<'pat, 'tcx>) + -> Option> { let candidate = candidate.clone(); let match_pairs = candidate.match_pairs; let result = self.match_pairs_under_assumption(test_lvalue, @@ -302,12 +302,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// Helper for candidate_under_assumption that does the actual /// work of transforming the list of match pairs. - fn match_pairs_under_assumption(&mut self, - test_lvalue: &Lvalue<'tcx>, - test_kind: &TestKind<'tcx>, - test_outcome: usize, - match_pairs: Vec>) - -> Option>> { + fn match_pairs_under_assumption<'pat>(&mut self, + test_lvalue: &Lvalue<'tcx>, + test_kind: &TestKind<'tcx>, + test_outcome: usize, + match_pairs: Vec>) + -> Option>> { let mut result = vec![]; for match_pair in match_pairs { @@ -357,12 +357,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// the discriminant equals 4, and we find that it does not, /// but the `match_pair` is testing if the discriminant equals 5, /// that does not help us. - fn test_informs_match_pair(&mut self, - match_pair: &MatchPair<'tcx>, - test_kind: &TestKind<'tcx>, - _test_outcome: usize) - -> bool { - match match_pair.pattern.kind { + fn test_informs_match_pair<'pat>(&mut self, + match_pair: &MatchPair<'pat, 'tcx>, + test_kind: &TestKind<'tcx>, + _test_outcome: usize) + -> bool { + match *match_pair.pattern.kind { PatternKind::Variant { .. } => { match *test_kind { TestKind::Switch { .. } => true, @@ -444,13 +444,13 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// On the second arm, a `None` will be returned, because if we /// observed that `option` has the discriminant `Ok`, then the /// second arm cannot apply. - pub fn consequent_match_pairs_under_assumption(&mut self, - match_pair: MatchPair<'tcx>, - test_kind: &TestKind<'tcx>, - test_outcome: usize) - -> Option>> { - match match_pair.pattern.kind { - PatternKind::Variant { adt_def, variant_index, subpatterns } => { + pub fn consequent_match_pairs_under_assumption<'pat>(&mut self, + match_pair: MatchPair<'pat, 'tcx>, + test_kind: &TestKind<'tcx>, + test_outcome: usize) + -> Option>> { + match *match_pair.pattern.kind { + PatternKind::Variant { adt_def, variant_index, ref subpatterns } => { assert!(match *test_kind { TestKind::Switch { .. } => true, _ => false }); @@ -464,12 +464,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { let elem = ProjectionElem::Downcast(adt_def, variant_index); let downcast_lvalue = match_pair.lvalue.clone().elem(elem); let consequent_match_pairs = - subpatterns.into_iter() + subpatterns.iter() .map(|subpattern| { let lvalue = downcast_lvalue.clone().field( subpattern.field); - self.match_pair(lvalue, subpattern.pattern) + MatchPair::new(lvalue, &subpattern.pattern) }) .collect(); Some(consequent_match_pairs) @@ -516,7 +516,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { } } - fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! { + fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! { self.hir.span_bug(match_pair.pattern.span, &format!("simplifyable pattern found: {:?}", match_pair.pattern)) } diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index 28925f9b38b4..18dde5537da4 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -15,26 +15,18 @@ use repr::*; use std::u32; impl<'a,'tcx> Builder<'a,'tcx> { - pub fn field_match_pairs(&mut self, - lvalue: Lvalue<'tcx>, - subpatterns: Vec>) - -> Vec> { - subpatterns.into_iter() + pub fn field_match_pairs<'pat>(&mut self, + lvalue: Lvalue<'tcx>, + subpatterns: &'pat [FieldPattern<'tcx>]) + -> Vec> { + subpatterns.iter() .map(|fieldpat| { let lvalue = lvalue.clone().field(fieldpat.field); - self.match_pair(lvalue, fieldpat.pattern) + MatchPair::new(lvalue, &fieldpat.pattern) }) .collect() } - pub fn match_pair(&mut self, - lvalue: Lvalue<'tcx>, - pattern: PatternRef<'tcx>) - -> MatchPair<'tcx> { - let pattern = self.hir.mirror(pattern); - MatchPair::new(lvalue, pattern) - } - /// When processing an array/slice pattern like `lv @ [x, y, ..s, z]`, /// this function converts the prefix (`x`, `y`) and suffix (`z`) into /// distinct match pairs: @@ -49,18 +41,17 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// tmp0 = lv[2..-1] // using the special Rvalue::Slice /// /// and creates a match pair `tmp0 @ s` - pub fn prefix_suffix_slice(&mut self, - match_pairs: &mut Vec>, - block: BasicBlock, - lvalue: Lvalue<'tcx>, - prefix: Vec>, - opt_slice: Option>, - suffix: Vec>) - -> BlockAnd<()> { + pub fn prefix_suffix_slice<'pat>(&mut self, + match_pairs: &mut Vec>, + block: BasicBlock, + lvalue: Lvalue<'tcx>, + prefix: &'pat [Pattern<'tcx>], + opt_slice: Option<&'pat Pattern<'tcx>>, + suffix: &'pat [Pattern<'tcx>]) + -> BlockAnd<()> { // If there is a `..P` pattern, create a temporary `t0` for // the slice and then a match pair `t0 @ P`: if let Some(slice) = opt_slice { - let slice = self.hir.mirror(slice); let prefix_len = prefix.len(); let suffix_len = suffix.len(); let rvalue = Rvalue::Slice { @@ -79,17 +70,17 @@ impl<'a,'tcx> Builder<'a,'tcx> { } /// Helper for `prefix_suffix_slice` which just processes the prefix and suffix. - fn prefix_suffix(&mut self, - match_pairs: &mut Vec>, - lvalue: Lvalue<'tcx>, - prefix: Vec>, - suffix: Vec>) { + fn prefix_suffix<'pat>(&mut self, + match_pairs: &mut Vec>, + lvalue: Lvalue<'tcx>, + prefix: &'pat [Pattern<'tcx>], + suffix: &'pat [Pattern<'tcx>]) { let min_length = prefix.len() + suffix.len(); assert!(min_length < u32::MAX as usize); let min_length = min_length as u32; let prefix_pairs: Vec<_> = - prefix.into_iter() + prefix.iter() .enumerate() .map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { @@ -98,12 +89,12 @@ impl<'a,'tcx> Builder<'a,'tcx> { from_end: false, }; let lvalue = lvalue.clone().elem(elem); - self.match_pair(lvalue, subpattern) + MatchPair::new(lvalue, subpattern) }) .collect(); let suffix_pairs: Vec<_> = - suffix.into_iter() + suffix.iter() .rev() .enumerate() .map(|(idx, subpattern)| { @@ -113,7 +104,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { from_end: true, }; let lvalue = lvalue.clone().elem(elem); - self.match_pair(lvalue, subpattern) + MatchPair::new(lvalue, subpattern) }) .collect(); @@ -121,8 +112,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { } } -impl<'tcx> MatchPair<'tcx> { - pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> { +impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { + pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> { MatchPair { lvalue: lvalue, pattern: pattern, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 56a20167b794..eb03727d9b2c 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hair; -use hair::cx::{Cx, PatNode}; +use hair::cx::Cx; use rustc::middle::region::CodeExtent; use rustc::middle::ty::{FnOutput, Ty}; use rustc_data_structures::fnv::FnvHashMap; @@ -78,7 +77,7 @@ macro_rules! unpack { pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>, _span: Span, implicit_arguments: Vec>, - explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>, + explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>, argument_extent: CodeExtent, return_ty: FnOutput<'tcx>, ast_block: &'tcx hir::Block) @@ -130,7 +129,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { fn args_and_body(&mut self, mut block: BasicBlock, implicit_arguments: Vec>, - explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>, + explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>, argument_extent: CodeExtent, ast_block: &'tcx hir::Block) -> BlockAnd>> @@ -148,9 +147,10 @@ impl<'a,'tcx> Builder<'a,'tcx> { .enumerate() .map(|(index, (ty, pattern))| { let lvalue = Lvalue::Arg(index as u32); + let pattern = this.hir.irrefutable_pat(pattern); unpack!(block = this.lvalue_into_pattern(block, argument_extent, - hair::PatternRef::Hair(pattern), + pattern, &lvalue)); ArgDecl { ty: ty } }); diff --git a/src/librustc_mir/build/stmt.rs b/src/librustc_mir/build/stmt.rs index 01fda2498f71..0c0816a2d9d2 100644 --- a/src/librustc_mir/build/stmt.rs +++ b/src/librustc_mir/build/stmt.rs @@ -40,7 +40,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { StmtKind::Let { remainder_scope, init_scope, pattern, initializer: None, stmts } => { this.in_scope(remainder_scope, block, |this| { unpack!(block = this.in_scope(init_scope, block, |this| { - this.declare_bindings(remainder_scope, pattern); + this.declare_bindings(remainder_scope, &pattern); block.unit() })); this.stmts(block, stmts) diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index a407c42372a8..bedcefe3b0da 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -10,7 +10,6 @@ use hair::*; use hair::cx::Cx; -use hair::cx::pattern::PatNode; use hair::cx::to_ref::ToRef; use rustc::middle::region::{BlockRemainder, CodeExtentData}; use rustc_front::hir; @@ -65,12 +64,13 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>, // they are within the scope of this let: let following_stmts = mirror_stmts(cx, block_id, stmts); + let pattern = cx.irrefutable_pat(&local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Let { remainder_scope: remainder_extent, init_scope: cx.tcx.region_maps.node_extent(id), - pattern: PatNode::irrefutable(&local.pat).to_ref(), + pattern: pattern, initializer: local.init.to_ref(), stmts: following_stmts, }, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a077cb6c7a3a..3fd895afa983 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -11,10 +11,8 @@ use hair::*; use repr::*; use rustc_data_structures::fnv::FnvHashMap; -use std::rc::Rc; use hair::cx::Cx; use hair::cx::block; -use hair::cx::pattern::PatNode; use hair::cx::to_ref::ToRef; use rustc::front::map; use rustc::middle::const_eval; @@ -486,19 +484,20 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { } } -fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { - let map = if arm.pats.len() == 1 { +fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { + let mut map; + let opt_map = if arm.pats.len() == 1 { None } else { - let mut map = FnvHashMap(); + map = FnvHashMap(); pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| { map.insert(path.node, p_id); }); - Some(Rc::new(map)) + Some(&map) }; Arm { - patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(), + patterns: arm.pats.iter().map(|p| cx.refutable_pat(opt_map, p)).collect(), guard: arm.guard.to_ref(), body: arm.body.to_ref(), } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 8d4b05afcb6e..70a64a5653a3 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -41,8 +41,6 @@ impl<'a,'tcx> Cx<'a,'tcx> { } } -pub use self::pattern::PatNode; - impl<'a,'tcx:'a> Cx<'a, 'tcx> { /// Normalizes `ast` into the appropriate `mirror` type. pub fn mirror>(&mut self, ast: M) -> M::Output { diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index fa9678041790..e9b58199023b 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -10,10 +10,8 @@ use hair::*; use hair::cx::Cx; -use hair::cx::to_ref::ToRef; use repr::*; use rustc_data_structures::fnv::FnvHashMap; -use std::rc::Rc; use rustc::middle::const_eval; use rustc::middle::def; use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding}; @@ -36,183 +34,111 @@ use syntax::ptr::P; /// _ => { ... } /// } /// ``` -#[derive(Clone, Debug)] -pub struct PatNode<'tcx> { - pat: &'tcx hir::Pat, - binding_map: Option>>, +struct PatCx<'patcx, 'cx: 'patcx, 'tcx: 'cx> { + cx: &'patcx mut Cx<'cx, 'tcx>, + binding_map: Option<&'patcx FnvHashMap>, } -impl<'tcx> PatNode<'tcx> { - pub fn new(pat: &'tcx hir::Pat, - binding_map: Option>>) - -> PatNode<'tcx> { - PatNode { - pat: pat, +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 refutable_pat(&mut self, + binding_map: Option<&FnvHashMap>, + pat: &'tcx hir::Pat) + -> Pattern<'tcx> { + PatCx::new(self, binding_map).to_pat(pat) + } +} + +impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { + fn new(cx: &'patcx mut Cx<'cx, 'tcx>, + binding_map: Option<&'patcx FnvHashMap>) + -> PatCx<'patcx, 'cx, 'tcx> { + PatCx { + cx: cx, binding_map: binding_map, } } - pub fn irrefutable(pat: &'tcx hir::Pat) -> PatNode<'tcx> { - PatNode::new(pat, None) - } - - fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<'tcx> { - PatNode::new(pat, self.binding_map.clone()).to_ref() - } - - fn pat_refs<'a>(&self, pats: &'tcx Vec>) -> Vec> { - pats.iter().map(|p| self.pat_ref(p)).collect() - } - - fn opt_pat_ref<'a>(&self, pat: &'tcx Option>) -> Option> { - pat.as_ref().map(|p| self.pat_ref(p)) - } - - fn slice_or_array_pattern<'a>(&self, - cx: &mut Cx<'a, 'tcx>, - ty: Ty<'tcx>, - prefix: &'tcx Vec>, - slice: &'tcx Option>, - suffix: &'tcx Vec>) - -> PatternKind<'tcx> { - match ty.sty { - ty::TySlice(..) => - // matching a slice or fixed-length array - PatternKind::Slice { - prefix: self.pat_refs(prefix), - slice: self.opt_pat_ref(slice), - suffix: self.pat_refs(suffix), - }, - - ty::TyArray(_, len) => { - // fixed-length array - assert!(len >= prefix.len() + suffix.len()); - PatternKind::Array { - prefix: self.pat_refs(prefix), - slice: self.opt_pat_ref(slice), - suffix: self.pat_refs(suffix), - } - } - - _ => { - cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc"); - } - } - } - - fn variant_or_leaf<'a>(&self, - cx: &mut Cx<'a, 'tcx>, - subpatterns: Vec>) - -> PatternKind<'tcx> { - let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); - match def { - def::DefVariant(enum_id, variant_id, _) => { - let adt_def = cx.tcx.lookup_adt_def(enum_id); - if adt_def.variants.len() > 1 { - PatternKind::Variant { - adt_def: adt_def, - variant_index: adt_def.variant_index_with_id(variant_id), - subpatterns: subpatterns, - } - } else { - PatternKind::Leaf { subpatterns: subpatterns } - } - } - - // NB: resolving to DefStruct means the struct *constructor*, - // not the struct as a type. - def::DefStruct(..) | def::DefTy(..) => { - PatternKind::Leaf { subpatterns: subpatterns } - } - - _ => { - cx.tcx.sess.span_bug(self.pat.span, - &format!("inappropriate def for pattern: {:?}", def)); - } - } - } -} - -impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { - type Output = Pattern<'tcx>; - - fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> { - let kind = match self.pat.node { + fn to_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> { + let kind = match pat.node { hir::PatWild => PatternKind::Wild, hir::PatLit(ref value) => { - let value = const_eval::eval_const_expr(cx.tcx, value); + let value = const_eval::eval_const_expr(self.cx.tcx, value); let value = Literal::Value { value: value }; PatternKind::Constant { value: value } } hir::PatRange(ref lo, ref hi) => { - let lo = const_eval::eval_const_expr(cx.tcx, lo); + let lo = const_eval::eval_const_expr(self.cx.tcx, lo); let lo = Literal::Value { value: lo }; - let hi = const_eval::eval_const_expr(cx.tcx, hi); + let hi = const_eval::eval_const_expr(self.cx.tcx, hi); let hi = Literal::Value { value: hi }; PatternKind::Range { lo: lo, hi: hi } }, hir::PatEnum(..) | hir::PatIdent(..) | hir::PatQPath(..) - if pat_is_resolved_const(&cx.tcx.def_map.borrow(), self.pat) => + if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) => { - let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); match def { def::DefConst(def_id) | def::DefAssociatedConst(def_id) => - match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.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( - cx.tcx, const_expr, + 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 = cx.tcx.mk_substs(Substs::empty()); + let substs = self.cx.tcx.mk_substs(Substs::empty()); Literal::Item { def_id: def_id, substs: substs } }; PatternKind::Constant { value: literal } } None => { - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("cannot eval constant: {:?}", def_id)) } }, _ => - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("def not a constant: {:?}", def)), } } hir::PatRegion(ref subpattern, _) | hir::PatBox(ref subpattern) => { - PatternKind::Deref { subpattern: self.pat_ref(subpattern) } + PatternKind::Deref { subpattern: self.to_pat(subpattern) } } hir::PatVec(ref prefix, ref slice, ref suffix) => { - let ty = cx.tcx.node_id_to_type(self.pat.id); + let ty = self.cx.tcx.node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { subpattern: Pattern { ty: mt.ty, - span: self.pat.span, - kind: self.slice_or_array_pattern(cx, mt.ty, prefix, - slice, suffix), - }.to_ref() + span: pat.span, + kind: Box::new(self.slice_or_array_pattern(pat, mt.ty, prefix, + slice, suffix)), + }, }, ty::TySlice(..) | ty::TyArray(..) => - self.slice_or_array_pattern(cx, ty, prefix, slice, suffix), + self.slice_or_array_pattern(pat, ty, prefix, slice, suffix), ref sty => - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("unexpanded type for vector pattern: {:?}", sty)), } } @@ -221,9 +147,9 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { let subpatterns = subpatterns.iter() .enumerate() - .map(|(i, subpattern)| FieldPatternRef { + .map(|(i, subpattern)| FieldPattern { field: Field::new(i), - pattern: self.pat_ref(subpattern), + pattern: self.to_pat(subpattern), }) .collect(); @@ -231,13 +157,13 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { } hir::PatIdent(bm, ref ident, ref sub) - if pat_is_binding(&cx.tcx.def_map.borrow(), self.pat) => + if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) => { let id = match self.binding_map { - None => self.pat.id, + None => pat.id, Some(ref map) => map[&ident.node.name], }; - let var_ty = cx.tcx.node_id_to_type(self.pat.id); + let var_ty = self.cx.tcx.node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(&r, _) => Some(r), _ => None, @@ -258,12 +184,12 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { name: ident.node.name, var: id, ty: var_ty, - subpattern: self.opt_pat_ref(sub), + subpattern: self.to_opt_pat(sub), } } hir::PatIdent(..) => { - self.variant_or_leaf(cx, vec![]) + self.variant_or_leaf(pat, vec![]) } hir::PatEnum(_, ref opt_subpatterns) => { @@ -271,26 +197,26 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { opt_subpatterns.iter() .flat_map(|v| v.iter()) .enumerate() - .map(|(i, field)| FieldPatternRef { + .map(|(i, field)| FieldPattern { field: Field::new(i), - pattern: self.pat_ref(field), + pattern: self.to_pat(field), }) .collect(); - self.variant_or_leaf(cx, subpatterns) + self.variant_or_leaf(pat, subpatterns) } hir::PatStruct(_, ref fields, _) => { - let pat_ty = cx.tcx.node_id_to_type(self.pat.id); + let pat_ty = self.cx.tcx.node_id_to_type(pat.id); let adt_def = match pat_ty.sty { ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def, _ => { - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, "struct pattern not applied to struct or enum"); } }; - let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); let variant_def = adt_def.variant_of_def(def); let subpatterns = @@ -298,31 +224,104 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { .map(|field| { let index = variant_def.index_of_field_named(field.node.name); let index = index.unwrap_or_else(|| { - cx.tcx.sess.span_bug( - self.pat.span, + self.cx.tcx.sess.span_bug( + pat.span, &format!("no field with name {:?}", field.node.name)); }); - FieldPatternRef { + FieldPattern { field: Field::new(index), - pattern: self.pat_ref(&field.node.pat), + pattern: self.to_pat(&field.node.pat), } }) .collect(); - self.variant_or_leaf(cx, subpatterns) + self.variant_or_leaf(pat, subpatterns) } hir::PatQPath(..) => { - cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc"); + self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc"); } }; - let ty = cx.tcx.node_id_to_type(self.pat.id); + let ty = self.cx.tcx.node_id_to_type(pat.id); Pattern { - span: self.pat.span, + span: pat.span, ty: ty, - kind: kind, + kind: Box::new(kind), + } + } + + fn to_pats(&mut self, pats: &'tcx Vec>) -> Vec> { + pats.iter().map(|p| self.to_pat(p)).collect() + } + + fn to_opt_pat(&mut self, pat: &'tcx Option>) -> Option> { + pat.as_ref().map(|p| self.to_pat(p)) + } + + fn slice_or_array_pattern(&mut self, + pat: &'tcx hir::Pat, + ty: Ty<'tcx>, + prefix: &'tcx Vec>, + slice: &'tcx Option>, + suffix: &'tcx Vec>) + -> 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), + } + } + + ty::TyArray(_, len) => { + // 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), + } + } + + _ => { + self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc"); + } + } + } + + fn variant_or_leaf(&mut self, + pat: &'tcx hir::Pat, + subpatterns: Vec>) + -> PatternKind<'tcx> { + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); + match def { + def::DefVariant(enum_id, variant_id, _) => { + let adt_def = self.cx.tcx.lookup_adt_def(enum_id); + if adt_def.variants.len() > 1 { + PatternKind::Variant { + adt_def: adt_def, + variant_index: adt_def.variant_index_with_id(variant_id), + subpatterns: subpatterns, + } + } else { + PatternKind::Leaf { subpatterns: subpatterns } + } + } + + // NB: resolving to DefStruct means the struct *constructor*, + // not the struct as a type. + def::DefStruct(..) | def::DefTy(..) => { + PatternKind::Leaf { subpatterns: subpatterns } + } + + _ => { + self.cx.tcx.sess.span_bug(pat.span, + &format!("inappropriate def for pattern: {:?}", def)); + } } } } diff --git a/src/librustc_mir/hair/cx/to_ref.rs b/src/librustc_mir/hair/cx/to_ref.rs index e0b8abfbd9ce..da200a8a33f0 100644 --- a/src/librustc_mir/hair/cx/to_ref.rs +++ b/src/librustc_mir/hair/cx/to_ref.rs @@ -10,7 +10,6 @@ use hair::*; -use hair::cx::pattern::PatNode; use rustc_front::hir; use syntax::ptr::P; @@ -43,22 +42,6 @@ impl<'a,'tcx:'a> ToRef for Expr<'tcx> { } } -impl<'a,'tcx:'a> ToRef for PatNode<'tcx> { - type Output = PatternRef<'tcx>; - - fn to_ref(self) -> PatternRef<'tcx> { - PatternRef::Hair(self) - } -} - -impl<'a,'tcx:'a> ToRef for Pattern<'tcx> { - type Output = PatternRef<'tcx>; - - fn to_ref(self) -> PatternRef<'tcx> { - PatternRef::Mirror(Box::new(self)) - } -} - impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option where &'tcx T: ToRef { diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index becaa19974d8..606679150142 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -22,7 +22,7 @@ use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty}; use rustc_front::hir; use syntax::ast; use syntax::codemap::Span; -use self::cx::{Cx, PatNode}; +use self::cx::Cx; pub mod cx; @@ -72,7 +72,7 @@ pub enum StmtKind<'tcx> { init_scope: CodeExtent, /// let = ... - pattern: PatternRef<'tcx>, + pattern: Pattern<'tcx>, /// let pat = ... initializer: Option>, @@ -252,7 +252,7 @@ pub struct FieldExprRef<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { - pub patterns: Vec>, + pub patterns: Vec>, pub guard: Option>, pub body: ExprRef<'tcx>, } @@ -261,7 +261,7 @@ pub struct Arm<'tcx> { pub struct Pattern<'tcx> { pub ty: Ty<'tcx>, pub span: Span, - pub kind: PatternKind<'tcx>, + pub kind: Box>, } #[derive(Copy, Clone, Debug)] @@ -281,23 +281,23 @@ pub enum PatternKind<'tcx> { mode: BindingMode, var: ast::NodeId, ty: Ty<'tcx>, - subpattern: Option>, + subpattern: Option>, }, // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants Variant { adt_def: AdtDef<'tcx>, variant_index: usize, - subpatterns: Vec>, + subpatterns: Vec>, }, // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant Leaf { - subpatterns: Vec>, + subpatterns: Vec>, }, Deref { - subpattern: PatternRef<'tcx>, + subpattern: Pattern<'tcx>, }, // box P, &P, &mut P, etc Constant { @@ -311,16 +311,16 @@ pub enum PatternKind<'tcx> { // matches against a slice, checking the length and extracting elements Slice { - prefix: Vec>, - slice: Option>, - suffix: Vec>, + prefix: Vec>, + slice: Option>, + suffix: Vec>, }, // fixed match against an array, irrefutable Array { - prefix: Vec>, - slice: Option>, - suffix: Vec>, + prefix: Vec>, + slice: Option>, + suffix: Vec>, }, } @@ -331,15 +331,9 @@ pub enum BindingMode { } #[derive(Clone, Debug)] -pub enum PatternRef<'tcx> { - Hair(PatNode<'tcx>), - Mirror(Box>), -} - -#[derive(Clone, Debug)] -pub struct FieldPatternRef<'tcx> { +pub struct FieldPattern<'tcx> { pub field: Field, - pub pattern: PatternRef<'tcx>, + pub pattern: Pattern<'tcx>, } /////////////////////////////////////////////////////////////////////////// @@ -400,25 +394,6 @@ impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> { } } -impl<'tcx> Mirror<'tcx> for Pattern<'tcx> { - type Output = Pattern<'tcx>; - - fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> { - self - } -} - -impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> { - type Output = Pattern<'tcx>; - - fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> { - match self { - PatternRef::Hair(h) => h.make_mirror(hir), - PatternRef::Mirror(m) => *m, - } - } -} - impl<'tcx> Mirror<'tcx> for Block<'tcx> { type Output = Block<'tcx>; diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 4302105dda2b..9362aeb6005c 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -23,7 +23,7 @@ extern crate rustc_front; use build; use dot; use repr::Mir; -use hair::cx::{PatNode, Cx}; +use hair::cx::Cx; use std::fs::File; use self::rustc::middle::infer; @@ -211,7 +211,7 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>, .iter() .enumerate() .map(|(index, arg)| { - (fn_sig.inputs[index], PatNode::irrefutable(&arg.pat)) + (fn_sig.inputs[index], &*arg.pat) }) .collect();