about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-05-13 03:10:46 -0700
committerbors <bors@rust-lang.org>2016-05-13 03:10:46 -0700
commita581c82bdc2c13a398b091878d7353bc3d097d59 (patch)
tree258da1aa36b7771eae1b1fb036df3f385aed7364
parent709e5c5fdefb26500bf1b6a1e7eff7a6dfb8596a (diff)
parente5a91b7ba1a22e34c7d09105e7a115e696ffcd0f (diff)
downloadrust-a581c82bdc2c13a398b091878d7353bc3d097d59.tar.gz
rust-a581c82bdc2c13a398b091878d7353bc3d097d59.zip
Auto merge of #33541 - eddyb:promote-only-temps, r=arielb1
mir: don't attempt to promote Unpromotable constant temps.

Fixes #33537. This was a non-problem in regular functions, but we also promote in `const fn`s.
There we always qualify temps so you can't depend on `Unpromotable` temps being `NOT_CONST`.
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs24
-rw-r--r--src/test/run-pass/issue-33537.rs24
2 files changed, 42 insertions, 6 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 54ac04bea9c..4eda1ed23b7 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -64,13 +64,18 @@ bitflags! {
         // pointer comparisons, ptr-to-int casts, etc.
         const NOT_CONST         = 1 << 6,
 
+        // Refers to temporaries which cannot be promoted as
+        // promote_consts decided they weren't simple enough.
+        const NOT_PROMOTABLE    = 1 << 7,
+
         // Borrows of temporaries can be promoted only
         // if they have none of the above qualifications.
-        const UNPROMOTABLE      = !0,
+        const NEVER_PROMOTE     = !0,
 
         // Const items can only have MUTABLE_INTERIOR
-        // without producing an error.
-        const CONST_ERROR       = !Qualif::MUTABLE_INTERIOR.bits
+        // and NOT_PROMOTABLE without producing an error.
+        const CONST_ERROR       = !Qualif::MUTABLE_INTERIOR.bits &
+                                  !Qualif::NOT_PROMOTABLE.bits
     }
 }
 
@@ -503,6 +508,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 self.add(Qualif::NOT_CONST);
             }
             Lvalue::Temp(index) => {
+                if !self.temp_promotion_state[index as usize].is_promotable() {
+                    self.add(Qualif::NOT_PROMOTABLE);
+                }
+
                 if let Some(qualif) = self.temp_qualif[index as usize] {
                     self.add(qualif);
                 } else {
@@ -688,8 +697,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 // We might have a candidate for promotion.
                 let candidate = Candidate::Ref(self.location);
                 if self.mode == Mode::Fn || self.mode == Mode::ConstFn {
-                    if !self.qualif.intersects(Qualif::UNPROMOTABLE) {
-                        self.promotion_candidates.push(candidate);
+                    if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
+                        // We can only promote direct borrows of temps.
+                        if let Lvalue::Temp(_) = *lvalue {
+                            self.promotion_candidates.push(candidate);
+                        }
                     }
                 }
             }
@@ -781,7 +793,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     this.visit_operand(arg);
                     if is_shuffle && i == 2 && this.mode == Mode::Fn {
                         let candidate = Candidate::ShuffleIndices(bb);
-                        if !this.qualif.intersects(Qualif::UNPROMOTABLE) {
+                        if !this.qualif.intersects(Qualif::NEVER_PROMOTE) {
                             this.promotion_candidates.push(candidate);
                         } else {
                             span_err!(this.tcx.sess, this.span, E0526,
diff --git a/src/test/run-pass/issue-33537.rs b/src/test/run-pass/issue-33537.rs
new file mode 100644
index 00000000000..24f4c9f590b
--- /dev/null
+++ b/src/test/run-pass/issue-33537.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 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(const_fn)]
+
+const fn foo() -> *const i8 {
+    b"foo" as *const _ as *const i8
+}
+
+const fn bar() -> i32 {
+    *&{(1, 2, 3).1}
+}
+
+fn main() {
+    assert_eq!(foo(), b"foo" as *const _ as *const i8);
+    assert_eq!(bar(), 2);
+}