-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Rustc doesn't error when trying to write to a const array #55721
Comments
"of course" not, you can't change constants, as they are (by definition) constant. If we changed that, we'd have a lot of problems (think about what something like What's going on here is totally not intuitive. Your code essentially expands to const FOO : [i32;1] = [0];
fn main() {
let mut tmp = FOO;
tmp[0] = 1;
println!("{:?}",FOO);
} which also doesn't produce any diagnostics. Maybe we could have a lint which tells you about "unused" variables like this, even if these variables are temporaries. |
This is ridiculous that such code even compiles: struct Thing(usize);
impl Thing {
fn set(&mut self, val: usize) {
self.0 = val;
}
}
const CONST_THING: Thing = Thing(0);
fn main() {
println!("Before: {}", CONST_THING.0);
CONST_THING.set(1);
println!("After: {}", CONST_THING.0);
} I just spent more than an hour figuring out what was wrong with my code because I accidentally defined one of my values as |
It turns out that there is a legitimate usage of this pattern with When you use the rust/src/libstd/thread/local.rs Lines 183 to 186 in 7c78a5f
A rust/src/libstd/thread/local.rs Lines 78 to 94 in 7c78a5f
If this kind of code is very uncommon (which I suspect it is), we could probably get away with whitelisting |
Another challenge is interior mutability: this code is probably fine: const EMPTY_VEC: Vec<u8> = Vec::new();
fn main() {
EMPTY_VEC.len();
} but this code isn't: use std::cell::Cell;
struct Foo {
inner: Cell<u8>
}
impl Foo {
fn sneaky_len(&self) -> u8 {
self.inner.replace(0)
}
}
const FOO: Foo = Foo { inner: Cell::new(25) };
fn main() {
assert_eq!(FOO.sneaky_len(), 25);
assert_eq!(FOO.sneaky_len(), 25);
let foo = FOO;
assert_eq!(foo.sneaky_len(), 25);
assert_eq!(foo.sneaky_len(), 0);
} |
…, r=oli-obk Add CONST_ITEM_MUTATION lint Fixes rust-lang#74053 Fixes rust-lang#55721 This PR adds a new lint `CONST_ITEM_MUTATION`. Given an item `const FOO: SomeType = ..`, this lint fires on: * Attempting to write directly to a field (`FOO.field = some_val`) or array entry (`FOO.array_field[0] = val`) * Taking a mutable reference to the `const` item (`&mut FOO`), including through an autoderef `FOO.some_mut_self_method()` The lint message explains that since each use of a constant creates a new temporary, the original `const` item will not be modified.
…, r=oli-obk Add CONST_ITEM_MUTATION lint Fixes rust-lang#74053 Fixes rust-lang#55721 This PR adds a new lint `CONST_ITEM_MUTATION`. Given an item `const FOO: SomeType = ..`, this lint fires on: * Attempting to write directly to a field (`FOO.field = some_val`) or array entry (`FOO.array_field[0] = val`) * Taking a mutable reference to the `const` item (`&mut FOO`), including through an autoderef `FOO.some_mut_self_method()` The lint message explains that since each use of a constant creates a new temporary, the original `const` item will not be modified.
When trying to write to a const array rustc does compile the code without throwing an error but does not assign the value to the array.
As an example
compiles and prints
Is this behavior intended or should the compiler stop with an error as it does when compiling the following code?
The text was updated successfully, but these errors were encountered: