diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index eb308f903d3dd..98ea6ce70151d 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -170,7 +170,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) { let mut static_inliner = StaticInliner::new(cx.tcx); let inlined_arms = arms.iter().map(|arm| { (arm.pats.iter().map(|pat| { - static_inliner.fold_pat((*pat).clone()) + static_inliner.inline_if_necessary(pat.clone()) }).collect(), arm.guard.as_ref().map(|e| &**e)) }).collect::>, Option<&Expr>)>>(); @@ -211,7 +211,8 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) { }, ExprForLoop(ref pat, _, _, _) => { let mut static_inliner = StaticInliner::new(cx.tcx); - is_refutable(cx, &*static_inliner.fold_pat((*pat).clone()), |uncovered_pat| { + let inlined_pat = static_inliner.inline_if_necessary(pat.clone()); + is_refutable(cx, &*inlined_pat, |uncovered_pat| { cx.tcx.sess.span_err( pat.span, format!("refutable pattern in `for` loop binding: \ @@ -220,7 +221,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) { }); // Check legality of move bindings. - check_legality_of_move_bindings(cx, false, slice::ref_slice(pat)); + check_legality_of_move_bindings(cx, false, slice::ref_slice(&*pat)); check_legality_of_bindings_in_at_patterns(cx, &**pat); } _ => () @@ -325,6 +326,19 @@ impl<'a, 'tcx> StaticInliner<'a, 'tcx> { } } +impl<'a, 'tcx> StaticInliner<'a, 'tcx> { + fn needs_inlining(&self, pat: &Pat) -> bool { + !walk_pat(pat, |p| !pat_is_const(&self.tcx.def_map, &*p)) + } + pub fn inline_if_necessary(&mut self, pat: P) -> P { + if self.needs_inlining(&*pat) { + self.fold_pat(pat) + } else { + pat + } + } +} + impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { fn fold_pat(&mut self, pat: P) -> P { match pat.node { @@ -864,7 +878,8 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) { }; let mut static_inliner = StaticInliner::new(cx.tcx); - is_refutable(cx, &*static_inliner.fold_pat(loc.pat.clone()), |pat| { + let inlined_pat = static_inliner.inline_if_necessary(loc.pat.clone()); + is_refutable(cx, &*inlined_pat, |pat| { span_err!(cx.tcx.sess, loc.pat.span, E0005, "refutable pattern in {} binding: `{}` not covered", name, pat_to_string(pat) diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index ac1a62b185231..1c6131c25390c 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -46,7 +46,7 @@ pub fn pat_is_const(dm: &resolve::DefMap, pat: &Pat) -> bool { match pat.node { PatIdent(_, _, None) | PatEnum(..) => { match dm.borrow().find(&pat.id) { - Some(&DefStatic(_, false)) => true, + Some(&DefStatic(_, _)) => true, _ => false } } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 755ff991fb60a..9cdf8d8b69470 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -222,7 +222,6 @@ use std::rc::Rc; use syntax::ast; use syntax::ast::{DUMMY_NODE_ID, Ident}; use syntax::codemap::Span; -use syntax::fold::Folder; use syntax::ptr::P; struct ConstantExpr<'a>(&'a ast::Expr); @@ -1351,7 +1350,9 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, let mut static_inliner = StaticInliner::new(scope_cx.tcx()); let arm_pats: Vec>> = arm_datas.iter().map(|arm_data| { - arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect() + arm_data.arm.pats.iter().map(|pat| + static_inliner.inline_if_necessary(pat.clone()) + ).collect() }).collect(); let mut matches = Vec::new(); for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) {