-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Allow assignments in const contexts #56070
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
bc543d7
Allow assignments in const contexts
oli-obk 59eff14
Also catch static mutation at evaluation time
oli-obk 7d5b5ff
Update nll stderr files
oli-obk f98235e
Document runtime static mutation checks
oli-obk 6bcb0d6
Explain missing error in test
oli-obk f70abe8
Add sanity test for promotion and `const_let`
oli-obk 7d96f2c
Document qualify_consts more
oli-obk 3e081c7
Trailing newline
oli-obk 37fcd5c
Grammar nit
oli-obk 301ce8b
Properly assign to aggregate fields
oli-obk 3c290a5
Ensure assignments don't allow skipping projection checks
oli-obk 42a3f73
Tidy
oli-obk e05b61c
Fix a comment
oli-obk 22aebd5
Add regression test for overwriting qualifs by assignment
oli-obk 6db8c6c
Explain why we do not overwrite qualification of locals
oli-obk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -243,13 +243,52 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { | |
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); | ||
if self.tcx.features().const_let { | ||
let mut dest = dest; | ||
let index = loop { | ||
match dest { | ||
// with `const_let` active, we treat all locals equal | ||
Place::Local(index) => break *index, | ||
// projections are transparent for assignments | ||
// we qualify the entire destination at once, even if just a field would have | ||
// stricter qualification | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't seem correct - if you assign something with less qualifications to a field of a value with more, you turn those bits off. |
||
Place::Projection(proj) => { | ||
// Catch more errors in the destination. `visit_place` also checks various | ||
// projection rules like union field access and raw pointer deref | ||
self.visit_place( | ||
dest, | ||
PlaceContext::MutatingUse(MutatingUseContext::Store), | ||
location | ||
); | ||
dest = &proj.base; | ||
}, | ||
Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"), | ||
Place::Static(..) => { | ||
// Catch more errors in the destination. `visit_place` also checks that we | ||
// do not try to access statics from constants or try to mutate statics | ||
self.visit_place( | ||
dest, | ||
PlaceContext::MutatingUse(MutatingUseContext::Store), | ||
location | ||
); | ||
oli-obk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return; | ||
} | ||
} | ||
}; | ||
debug!("store to var {:?}", index); | ||
match &mut self.local_qualif[index] { | ||
// this is overly restrictive, because even full assignments do not clear the qualif | ||
// While we could special case full assignments, this would be inconsistent with | ||
// aggregates where we overwrite all fields via assignments, which would not get | ||
// that feature. | ||
Some(ref mut qualif) => *qualif = *qualif | self.qualif, | ||
oli-obk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// insert new qualification | ||
qualif @ None => *qualif = Some(self.qualif), | ||
} | ||
return; | ||
} | ||
|
||
match *dest { | ||
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 +517,16 @@ 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() { | ||
// this is not strictly necessary as miri will also bail out | ||
// For interior mutability we can't really catch this statically as that | ||
// goes through raw pointers and intermediate temporaries, so miri has | ||
// to catch this anyway | ||
self.tcx.sess.span_err( | ||
self.span, | ||
"cannot mutate statics in the initializer of another static", | ||
); | ||
} | ||
return; | ||
} | ||
self.add(Qualif::NOT_CONST); | ||
|
30 changes: 30 additions & 0 deletions
30
src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// 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; //~ ERROR could not evaluate static initializer | ||
}; | ||
|
||
fn main() {} |
9 changes: 9 additions & 0 deletions
9
src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0080]: could not evaluate static initializer | ||
--> $DIR/assign-to-static-within-other-static-2.rs:27:5 | ||
| | ||
LL | *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer | ||
| ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0080`. |
24 changes: 24 additions & 0 deletions
24
src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// 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; | ||
|
||
static mut FOO: u32 = 42; | ||
static BOO: () = unsafe { | ||
FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static | ||
}; | ||
|
||
fn main() {} |
8 changes: 8 additions & 0 deletions
8
src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
error: cannot mutate statics in the initializer of another static | ||
--> $DIR/assign-to-static-within-other-static.rs:21:5 | ||
| | ||
LL | FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static | ||
| ^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 2 additions & 11 deletions
13
src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
| | ||
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`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// compile-pass | ||
|
||
#![feature(const_let)] | ||
|
||
struct S(i32); | ||
|
||
const A: () = { | ||
let mut s = S(0); | ||
s.0 = 1; | ||
}; | ||
|
||
fn main() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#![feature(const_let)] | ||
|
||
use std::cell::Cell; | ||
|
||
const FOO: &(Cell<usize>, bool) = { | ||
let mut a = (Cell::new(0), false); | ||
a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)` | ||
&{a} //~ ERROR cannot borrow a constant which may contain interior mutability | ||
}; | ||
|
||
fn main() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead | ||
--> $DIR/partial_qualif.rs:8:5 | ||
| | ||
LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability | ||
| ^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0492`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#![feature(const_let)] | ||
|
||
use std::cell::Cell; | ||
|
||
const FOO: &u32 = { | ||
let mut a = 42; | ||
{ | ||
let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values | ||
unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants | ||
} | ||
&{a} | ||
}; | ||
|
||
fn main() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
error[E0017]: references in constants may only refer to immutable values | ||
--> $DIR/projection_qualif.rs:8:27 | ||
| | ||
LL | let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values | ||
| ^^^^^^ constants require immutable values | ||
|
||
error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911) | ||
--> $DIR/projection_qualif.rs:9:18 | ||
| | ||
LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants | ||
| ^^^^^^ | ||
| | ||
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
Some errors occurred: E0017, E0658. | ||
For more information about an error, try `rustc --explain E0017`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
error[E0597]: `y` does not live long enough | ||
--> $DIR/promote_const_let.rs:6:9 | ||
| | ||
LL | let x: &'static u32 = { | ||
| ------------ type annotation requires that `y` is borrowed for `'static` | ||
LL | let y = 42; | ||
LL | &y //~ ERROR does not live long enough | ||
| ^^ borrowed value does not live long enough | ||
LL | }; | ||
| - `y` dropped here while still borrowed | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.