about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-19 11:19:14 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-19 11:19:14 +0100
commitbc543d7e6c4c87f99eea4dc6217eee54cd7f18b1 (patch)
tree004e4cf471dedefe96c08af34770b23af4814813
parent7e82eda000c8d4abbdaa76b3563cd77f938fc411 (diff)
downloadrust-bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1.tar.gz
rust-bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1.zip
Allow assignments in const contexts
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs34
-rw-r--r--src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs35
-rw-r--r--src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr8
-rw-r--r--src/test/ui/consts/const-eval/mod-static-with-const-fn.rs5
-rw-r--r--src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr15
-rw-r--r--src/test/ui/consts/const_let_assign.rs12
-rw-r--r--src/test/ui/consts/const_let_assign2.rs25
-rw-r--r--src/test/ui/consts/const_let_assign3.rs22
-rw-r--r--src/test/ui/consts/const_let_assign3.stderr9
9 files changed, 143 insertions, 22 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 00309b0a3e9..31a0dc1494c 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -243,13 +243,29 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
             return;
         }
 
+        if self.tcx.features().const_let {
+            let mut dest = dest;
+            let index = loop {
+                match dest {
+                    Place::Local(index) => break *index,
+                    Place::Projection(proj) => dest = &proj.base,
+                    Place::Promoted(..) | Place::Static(..) => {
+                        // Catch more errors in the destination.
+                        self.visit_place(
+                            dest,
+                            PlaceContext::MutatingUse(MutatingUseContext::Store),
+                            location
+                        );
+                        return;
+                    }
+                }
+            };
+            debug!("store to var {:?}", index);
+            self.local_qualif[index] = Some(self.qualif);
+            return;
+        }
+
         match *dest {
-            Place::Local(index) if (self.mir.local_kind(index) == LocalKind::Var ||
-                                   self.mir.local_kind(index) == LocalKind::Arg) &&
-                                   self.tcx.sess.features_untracked().const_let => {
-                debug!("store to var {:?}", index);
-                self.local_qualif[index] = Some(self.qualif);
-            }
             Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp ||
                                    self.mir.local_kind(index) == LocalKind::ReturnPointer => {
                 debug!("store to {:?} (temp or return pointer)", index);
@@ -478,6 +494,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
 
                 // Only allow statics (not consts) to refer to other statics.
                 if self.mode == Mode::Static || self.mode == Mode::StaticMut {
+                    if context.is_mutating_use() {
+                        self.tcx.sess.span_err(
+                            self.span,
+                            "cannot mutate statics in the initializer of another static",
+                        );
+                    }
                     return;
                 }
                 self.add(Qualif::NOT_CONST);
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
new file mode 100644
index 00000000000..5113d73b384
--- /dev/null
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
@@ -0,0 +1,35 @@
+// Copyright 2018 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.
+
+// New test for #53818: modifying static memory at compile-time is not allowed.
+// The test should never compile successfully
+
+#![feature(const_raw_ptr_deref)]
+#![feature(const_let)]
+
+use std::cell::UnsafeCell;
+
+struct Foo(UnsafeCell<u32>);
+
+unsafe impl Send for Foo {}
+unsafe impl Sync for Foo {}
+
+static FOO: Foo = Foo(UnsafeCell::new(42));
+
+static BAR: () = unsafe {
+    *FOO.0.get() = 5;
+};
+
+static mut FOO2: u32 = 42;
+static BOO2: () = unsafe {
+    FOO2 = 5;
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
new file mode 100644
index 00000000000..87f02e8e4cf
--- /dev/null
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
@@ -0,0 +1,8 @@
+error: cannot mutate statics in the initializer of another static
+  --> $DIR/assign-to-static-within-other-static.rs:32:5
+   |
+LL |     FOO2 = 5;
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
index 4136a7b6a72..600931e49a0 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // New test for #53818: modifying static memory at compile-time is not allowed.
-// The test should never succeed.
+// The test should never compile successfully
 
 #![feature(const_raw_ptr_deref)]
 #![feature(const_let)]
@@ -27,9 +27,6 @@ fn foo() {}
 
 static BAR: () = unsafe {
     *FOO.0.get() = 5;
-    //~^ ERROR statements in statics are unstable (see issue #48821)
-    // This error is caused by a separate bug that the feature gate error is reported
-    // even though the feature gate "const_let" is active.
 
     foo();
     //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
index c2bba27e4d1..899fc24f153 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
@@ -1,18 +1,9 @@
-error[E0658]: statements in statics are unstable (see issue #48821)
-  --> $DIR/mod-static-with-const-fn.rs:29:5
-   |
-LL |     *FOO.0.get() = 5;
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/mod-static-with-const-fn.rs:34:5
+  --> $DIR/mod-static-with-const-fn.rs:31:5
    |
 LL |     foo();
    |     ^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/const_let_assign.rs b/src/test/ui/consts/const_let_assign.rs
new file mode 100644
index 00000000000..a3c53a451e1
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![feature(const_let)]
+
+struct S(i32);
+
+const A: () = {
+    let mut s = S(0);
+    s.0 = 1;
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const_let_assign2.rs b/src/test/ui/consts/const_let_assign2.rs
new file mode 100644
index 00000000000..0de7396501a
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign2.rs
@@ -0,0 +1,25 @@
+// compile-pass
+
+#![feature(const_let)]
+#![feature(const_fn)]
+
+pub struct AA {
+    pub data: [u8; 10],
+}
+
+impl AA {
+    pub const fn new() -> Self {
+        let mut res: AA = AA { data: [0; 10] };
+        res.data[0] = 5;
+        res
+    }
+}
+
+static mut BB: AA = AA::new();
+
+fn main() {
+    let ptr = unsafe { &mut BB };
+    for a in ptr.data.iter() {
+        println!("{}", a);
+    }
+}
diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs
new file mode 100644
index 00000000000..83825456b5c
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign3.rs
@@ -0,0 +1,22 @@
+#![feature(const_let)]
+#![feature(const_fn)]
+
+struct S {
+    state: u32,
+}
+
+impl S {
+    const fn foo(&mut self, x: u32) {
+        self.state = x;
+    }
+}
+
+const FOO: S = {
+    let mut s = S { state: 42 };
+    s.foo(3); //~ ERROR references in constants may only refer to immutable values
+    s
+};
+
+fn main() {
+    assert_eq!(FOO.state, 3);
+}
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
new file mode 100644
index 00000000000..7f9a953c10f
--- /dev/null
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -0,0 +1,9 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/const_let_assign3.rs:16:5
+   |
+LL |     s.foo(3); //~ ERROR references in constants may only refer to immutable values
+   |     ^ constants require immutable values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0017`.