diff options
| author | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2018-11-19 11:19:14 +0100 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2018-11-19 11:19:14 +0100 |
| commit | bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1 (patch) | |
| tree | 004e4cf471dedefe96c08af34770b23af4814813 | |
| parent | 7e82eda000c8d4abbdaa76b3563cd77f938fc411 (diff) | |
| download | rust-bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1.tar.gz rust-bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1.zip | |
Allow assignments in const contexts
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`. |
