about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-05-10 21:26:34 +0300
committerEduard Burtescu <edy.burt@gmail.com>2016-05-10 21:26:34 +0300
commite5a91b7ba1a22e34c7d09105e7a115e696ffcd0f (patch)
tree2d96a4defdd7731c7ef230d16662456d8ca61ecc
parentd6588097d4d65e567fb234c042e61ad8ce4d41e6 (diff)
downloadrust-e5a91b7ba1a22e34c7d09105e7a115e696ffcd0f.tar.gz
rust-e5a91b7ba1a22e34c7d09105e7a115e696ffcd0f.zip
mir: don't attempt to promote Unpromotable constant temps.
-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 90823528973..e7693d2691b 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -65,13 +65,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
     }
 }
 
@@ -502,6 +507,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, '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 {
@@ -687,8 +696,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, '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);
+                        }
                     }
                 }
             }
@@ -780,7 +792,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, '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);
+}