-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add CONST_ITEM_MUTATION lint #75573
Add CONST_ITEM_MUTATION lint #75573
Conversation
r? @oli-obk (rust_highfive has picked a reviewer for you, use r? to override) |
LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
warning: taking a mutable reference to a `const` item |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems quite verbose - I'm open to suggestions as to how to condense this information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eventually in the next Rust edition this warning could become an error?
LL | const ARRAY: [u8; 1] = [25]; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like the "^" to be cover the name and type, like this:
LL | const ARRAY: [u8; 1] = [25]; | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
LL | const ARRAY: [u8; 1] = [25]; | |
| ^^^^^^^^^^^^^^^^^^^^ |
The reason is the const expression in RHS could be a big block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we decide to do this, I think it should be done consistently (e.g. as a part of #75465), rather than special-casing this lint.
MY_STRUCT.field = false; //~ WARN attempting to modify | ||
MY_STRUCT.inner_array[0] = 'b'; //~ WARN attempting to modify | ||
MY_STRUCT.use_mut(); //~ WARN taking | ||
&mut MY_STRUCT; //~ WARN taking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your lint will also catch
let x = &mut MY_STRUCT;
which seems to me to be equivalent to let x = &mut Default::default()
or similar things that (arguably rarely) are legitimite use cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's intentional - I think let x = &mut MY_STRUCT
looks extremely misleading. If it there's ever the need for it in practice (maybe macro-generated code?), users can add #[allow(const_item_mutation)]
.
However, this shouldn't become a hard error.
We have rules about new lints, I'm not sure this warrants a rustc lint. I'd be fine with adding the relevant information to MIR but adding the lint to clippy (cc rust-lang/rust-clippy#829). @rust-lang/clippy what do you think? |
I think directly assigning to fields of a const should be a rust lint - it's completely useless (other than consuming the RHS), and always indicates a bug. I think this should be considered a natural extension of forbidding using a constant directly in the LHS of an assignment. Calling a const MY_VEC: Vec<u8> = Vec::new();
MY_VEC.push(25); which might come about as a result of several unrelated refactoring (changing a I don't know what the official policy is w.r.t adding new lints to rustc vs clippy. IMHO, 'correctness' lints which detect obviously broken code belong in rustc, not clippy. Assuming that there are no false positives, I see no downsides other than breaking |
Well... I'm not sure how strongly that rule is followed, but new lints in rustc need an RFC. Maybe an MCP is good enough here though. You can open an MCP here. It's not that much effort, just writing a few sentences of explanation and linking to the clippy and rustc issues and this PR should be enough. We'll then bring it up at the compiler team mtg |
@oli-obk MCP opened at rust-lang/compiler-team#345 |
Clippy already has a lint which implements part of the proposed lint: Playground I would be good with stop linting assignments to constants in the There was an issue opened in Clippy before, asking for the |
I'm ok with adding this lint to Clippy. We can implement it in the rust repo and then sync it back later. If it gets implemented directly in rustc, it would be great to stop linting on const assignments in |
I concur with @flip1995 I'm not against adding it to rustc directly, however rustc typically has a more onerous process for adding lints, so it's up to you! |
@oli-obk: The MCP has been accepted at rust-lang/compiler-team#345 - what is the next step? |
Now we review the impl and merge it. I won't be able to get to this until the 7th though, so if someone else grabs it in that time, I won't complain. |
☔ The latest upstream changes (presumably #74862) made this pull request unmergeable. Please resolve the merge conflicts. |
2aebd52
to
b2629b7
Compare
It would be great if you could assure in this PR, that the cases in |
b2629b7
to
414c83e
Compare
This comment has been minimized.
This comment has been minimized.
Oh, my mistake. Probably another orthogonal lint but requires sign off from language team. |
☔ The latest upstream changes (presumably #75077) made this pull request unmergeable. Please resolve the merge conflicts. |
414c83e
to
de2845a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lgtm now. Just some nits, then we can merge it
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.
de2845a
to
f422ef1
Compare
Clippy stderr diff: temporary_assignment.rs-error: assignment to temporary
- --> $DIR/temporary_assignment.rs:47:5
- |
-LL | Struct { field: 0 }.field = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `-D clippy::temporary-assignment` implied by `-D warnings`
-
-error: assignment to temporary
- --> $DIR/temporary_assignment.rs:48:5
- |
-LL | / MultiStruct {
-LL | | structure: Struct { field: 0 },
-LL | | }
-LL | | .structure
-LL | | .field = 1;
- | |______________^
-
-error: assignment to temporary
- --> $DIR/temporary_assignment.rs:53:5
- |
-LL | ArrayStruct { array: [0] }.array[0] = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: assignment to temporary
- --> $DIR/temporary_assignment.rs:54:5
- |
-LL | (0, 0).0 = 1;
- | ^^^^^^^^^^^^
-
-error: assignment to temporary
+error: attempting to modify a `const` item
--> $DIR/temporary_assignment.rs:56:5
|
LL | A.0 = 2;
| ^^^^^^^
+ |
+ = note: `-D const-item-mutation` implied by `-D warnings`
+ = note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
+note: `const` item defined here
+ --> $DIR/temporary_assignment.rs:36:1
+ |
+LL | const A: TupleStruct = TupleStruct(1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: assignment to temporary
+error: attempting to modify a `const` item
--> $DIR/temporary_assignment.rs:57:5
|
LL | B.field = 2;
| ^^^^^^^^^^^
+ |
+ = note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
+note: `const` item defined here
+ --> $DIR/temporary_assignment.rs:37:1
+ |
+LL | const B: Struct = Struct { field: 1 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: assignment to temporary
+error: attempting to modify a `const` item
--> $DIR/temporary_assignment.rs:58:5
|
LL | C.structure.field = 2;
| ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
+note: `const` item defined here
+ --> $DIR/temporary_assignment.rs:38:1
+ |
+LL | / const C: MultiStruct = MultiStruct {
+LL | | structure: Struct { field: 1 },
+LL | | };
+ | |__^
-error: assignment to temporary
+error: attempting to modify a `const` item
--> $DIR/temporary_assignment.rs:59:5
|
LL | D.array[0] = 2;
| ^^^^^^^^^^^^^^
+ |
+ = note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
+note: `const` item defined here
+ --> $DIR/temporary_assignment.rs:41:1
+ |
+LL | const D: ArrayStruct = ArrayStruct { array: [1] };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors borrow_interior_mutable_const.rs-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:65:5
+error: taking a mutable reference to a `const` item
+ --> $DIR/borrow_interior_mutable_const.rs:72:21
|
-LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
- | ^^^^^^
- |
- = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:66:16
- |
-LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
- | ^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:69:22
- |
-LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
- | ^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:70:25
- |
-LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
- | ^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:71:27
- |
-LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
- | ^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:72:26
- |
LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
- | ^^^^^^^^^
+ | ^^^^^^^^^^^^^^
|
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:83:14
+ = note: `-D const-item-mutation` implied by `-D warnings`
+ = note: each usage of a `const` item creates a new temporary
+ = note: the mutable reference will refer to this temporary, not the original `const` item
+note: `const` item defined here
+ --> $DIR/borrow_interior_mutable_const.rs:19:1
|
-LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
- | ^^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
+LL | const ONCE_INIT: Once = Once::new();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:84:14
- |
-LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
- | ^^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:85:19
- |
-LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
- | ^^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:86:14
- |
-LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
- | ^^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:87:13
- |
-LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
- | ^^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:93:13
- |
-LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
- | ^^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:98:5
- |
-LL | CELL.set(2); //~ ERROR interior mutability
- | ^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:99:16
- |
-LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
- | ^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:112:5
- |
-LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
- | ^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: a `const` item with interior mutability should not be borrowed
- --> $DIR/borrow_interior_mutable_const.rs:113:16
- |
-LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
- | ^^^^^^^^^^^
- |
- = help: assign this const to a local or static variable, and use the variable here
-
-error: aborting due to 16 previous errors
+error: aborting due to previous error |
I don't understand why the |
Maybe rustc lints are executed before Clippy lints and since these lints error ( The fix for this is, that the In the |
We no longer lint assignments to const item fields in the `temporary_assignment` lint, since this is now covered by the `CONST_ITEM_MUTATION` lint. Additionally, we `#![allow(const_item_mutation)]` in the `borrow_interior_mutable_const.rs` test. Clippy UI tests are run with `-D warnings`, which seems to cause builtin lints to prevent Clippy lints from running.
@bors r+ |
📌 Commit 4434e8c has been approved by |
☀️ Test successful - checks-actions, checks-azure |
…, 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.
CONST_ITEM_MUTATION list[1] warns mutable copy of STDIN and STDOUT when creating UEFI SystemTable. This commit suppresses the warnings. [1] rust-lang/rust#75573 Signed-off-by: Akira Moroo <retrage01@gmail.com>
CONST_ITEM_MUTATION list[1] warns mutable copy of STDIN and STDOUT when creating UEFI SystemTable. This commit fixes these warnings. [1] rust-lang/rust#75573 Signed-off-by: Akira Moroo <retrage01@gmail.com> Signed-off-by: Joe Richey <joerichey@google.com>
CONST_ITEM_MUTATION list[1] warns mutable copy of STDIN and STDOUT when creating UEFI SystemTable. This commit fixes these warnings. [1] rust-lang/rust#75573 Signed-off-by: Akira Moroo <retrage01@gmail.com> Signed-off-by: Joe Richey <joerichey@google.com>
CONST_ITEM_MUTATION list[1] warns mutable copy of STDIN and STDOUT when creating UEFI SystemTable. This commit fixes these warnings. [1] rust-lang/rust#75573 Signed-off-by: Akira Moroo <retrage01@gmail.com> Signed-off-by: Joe Richey <joerichey@google.com>
CONST_ITEM_MUTATION list[1] warns mutable copy of STDIN and STDOUT when creating UEFI SystemTable. This commit fixes these warnings. [1] rust-lang/rust#75573 Signed-off-by: Akira Moroo <retrage01@gmail.com> Signed-off-by: Joe Richey <joerichey@google.com>
Fixes #74053
Fixes #55721
This PR adds a new lint
CONST_ITEM_MUTATION
.Given an item
const FOO: SomeType = ..
, this lint fires on:FOO.field = some_val
) orarray entry (
FOO.array_field[0] = val
)const
item (&mut FOO
), includingthrough 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.