From bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 19 Nov 2018 11:19:14 +0100 Subject: [PATCH] Allow assignments in const contexts --- src/librustc_mir/transform/qualify_consts.rs | 34 ++++++++++++++---- .../assign-to-static-within-other-static.rs | 35 +++++++++++++++++++ ...ssign-to-static-within-other-static.stderr | 8 +++++ .../const-eval/mod-static-with-const-fn.rs | 5 +-- .../mod-static-with-const-fn.stderr | 15 ++------ src/test/ui/consts/const_let_assign.rs | 12 +++++++ src/test/ui/consts/const_let_assign2.rs | 25 +++++++++++++ src/test/ui/consts/const_let_assign3.rs | 22 ++++++++++++ src/test/ui/consts/const_let_assign3.stderr | 9 +++++ 9 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr create mode 100644 src/test/ui/consts/const_let_assign.rs create mode 100644 src/test/ui/consts/const_let_assign2.rs create mode 100644 src/test/ui/consts/const_let_assign3.rs create mode 100644 src/test/ui/consts/const_let_assign3.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 00309b0a3e905..31a0dc1494ce1 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 0000000000000..5113d73b38414 --- /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 or the MIT license +// , 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); + +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 0000000000000..87f02e8e4cf7e --- /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 4136a7b6a724f..600931e49a08e 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 c2bba27e4d1e2..899fc24f153a5 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 0000000000000..a3c53a451e106 --- /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 0000000000000..0de7396501adc --- /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 0000000000000..83825456b5c61 --- /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 0000000000000..7f9a953c10fe8 --- /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`.