about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2017-01-11 09:50:24 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-01-11 09:50:24 +0200
commit61b0b212f9609e56f06a63db8542c3a5288074d8 (patch)
tree1dd9d3fb54d20043bfc1ad49c7d14cd173ffbe9c /src
parent7ef1a69d2e05d86e0893763d2c86677e9c5f3d99 (diff)
downloadrust-61b0b212f9609e56f06a63db8542c3a5288074d8.tar.gz
rust-61b0b212f9609e56f06a63db8542c3a5288074d8.zip
fix function arguments in constant promotion
we can't create the target block until *after* we promote the arguments
- otherwise the arguments will be promoted into the target block. oops.

Fixes #38985.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/transform/promote_consts.rs28
-rw-r--r--src/test/run-pass/issue-37991.rs7
2 files changed, 22 insertions, 13 deletions
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index ec678339066..57cf4b1e8b0 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -237,7 +237,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             self.visit_rvalue(&mut rvalue, loc);
             self.assign(new_temp, rvalue, source_info.span);
         } else {
-            let mut terminator = if self.keep_original {
+            let terminator = if self.keep_original {
                 self.source[loc.block].terminator().clone()
             } else {
                 let terminator = self.source[loc.block].terminator_mut();
@@ -255,28 +255,30 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 }
             };
 
-            let last = self.promoted.basic_blocks().last().unwrap();
-            let new_target = self.new_block();
-
-            terminator.kind = match terminator.kind {
+            match terminator.kind {
                 TerminatorKind::Call { mut func, mut args, .. } => {
                     self.visit_operand(&mut func, loc);
                     for arg in &mut args {
                         self.visit_operand(arg, loc);
                     }
-                    TerminatorKind::Call {
-                        func: func,
-                        args: args,
-                        cleanup: None,
-                        destination: Some((Lvalue::Local(new_temp), new_target))
-                    }
+
+                    let last = self.promoted.basic_blocks().last().unwrap();
+                    let new_target = self.new_block();
+
+                    *self.promoted[last].terminator_mut() = Terminator {
+                        kind: TerminatorKind::Call {
+                            func: func,
+                            args: args,
+                            cleanup: None,
+                            destination: Some((Lvalue::Local(new_temp), new_target))
+                        },
+                        ..terminator
+                    };
                 }
                 ref kind => {
                     span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
                 }
             };
-
-            *self.promoted[last].terminator_mut() = terminator;
         };
 
         self.keep_original = old_keep_original;
diff --git a/src/test/run-pass/issue-37991.rs b/src/test/run-pass/issue-37991.rs
index cacc653871a..9bdde02d006 100644
--- a/src/test/run-pass/issue-37991.rs
+++ b/src/test/run-pass/issue-37991.rs
@@ -14,7 +14,14 @@ const fn foo() -> i64 {
     3
 }
 
+const fn bar(x: i64) -> i64 {
+    x*2
+}
+
 fn main() {
     let val = &(foo() % 2);
     assert_eq!(*val, 1);
+
+    let val2 = &(bar(1+1) % 3);
+    assert_eq!(*val2, 1);
 }