From 5dca9fb261b5bf7e8c77c3a23fa3c203b469d3b9 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Mon, 4 Aug 2014 18:58:06 -0700 Subject: [PATCH] librustc: Also use new alloca if matching on an arg or upvar which we reassign in the arm body. --- src/librustc/middle/trans/_match.rs | 7 +++-- src/test/run-pass/issue-15571.rs | 48 +++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index d8cbf5a2341e5..85b6294ae34e6 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1298,7 +1298,8 @@ pub fn trans_match<'a>( fn is_discr_reassigned(bcx: &Block, discr: &ast::Expr, body: &ast::Expr) -> bool { match discr.node { ast::ExprPath(..) => match bcx.def(discr.id) { - def::DefLocal(vid, _) | def::DefBinding(vid, _) => { + def::DefArg(vid, _) | def::DefBinding(vid, _) | + def::DefLocal(vid, _) | def::DefUpvar(vid, _, _, _) => { let mut rc = ReassignmentChecker { node: vid, reassigned: false @@ -1326,9 +1327,11 @@ impl euv::Delegate for ReassignmentChecker { fn borrow(&mut self, _: ast::NodeId, _: Span, _: mc::cmt, _: ty::Region, _: ty::BorrowKind, _: euv::LoanCause) {} fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {} + fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) { match cmt.cat { - mc::cat_local(vid) => self.reassigned = self.node == vid, + mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: vid, .. }) | + mc::cat_arg(vid) | mc::cat_local(vid) => self.reassigned = self.node == vid, _ => {} } } diff --git a/src/test/run-pass/issue-15571.rs b/src/test/run-pass/issue-15571.rs index 1a1618fbc48fa..0ef0fc83c9456 100644 --- a/src/test/run-pass/issue-15571.rs +++ b/src/test/run-pass/issue-15571.rs @@ -8,13 +8,57 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { +fn match_on_local() { let mut foo = Some(box 5i); match foo { None => {}, Some(x) => { foo = Some(x); } - }; + } println!("'{}'", foo.unwrap()); } + +fn match_on_arg(mut foo: Option>) { + match foo { + None => {} + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); +} + +fn match_on_binding() { + match Some(box 7i) { + mut foo => { + match foo { + None => {}, + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); + } + } +} + +fn match_on_upvar() { + let mut foo = Some(box 8i); + (proc() { + match foo { + None => {}, + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); + })(); +} + +fn main() { + match_on_local(); + match_on_arg(Some(box 6i)); + match_on_binding(); + match_on_upvar(); +}