-
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
Disallow *references* to static mut
[Edition Idea]
#114447
Comments
I think that this would be much better if methods on a type could take |
We discussed this in the lang team meeting today, and the consensus was in favour of going in this direction. (With https://doc.rust-lang.org/std/cell/struct.SyncUnsafeCell.html and https://doc.rust-lang.org/std/ptr/macro.addr_of_mut.html we have options that we didn't back in 2018.) Steps needed, I think:
|
@rustbot claim |
@rustbot labels -I-lang-nominated I'm going to unnominate this, since there's nothing more to discuss until there is a PR to review. Please nominate such a PR as soon as it is posted. (This is correctly labeled so we can track it with other ideas for the next edition without the nomination.) |
@obeis Any updates? Have you managed to make progress here? |
@scottmcm almost done. I will submit my pull request within the next two days at the latest. I apologize for the delay. |
While implementing the lint in #117556, the question came up whether various cases of implicitly taking a reference should be linted against: static mut STATIC = &[0, 1, 2];
let _ = STATIC.len();
let _ = STATIC[0];
let _ = format!("{}", STATIC); The three listed cases are (fairly) harmless. However, @scottmcm (and t-lang in general), what is your opinion on that? |
Personally I lean towards deprecating these cases, too, if the idea is that we want to mostly deprecate |
I think this should be linting about anything that's created enough of a reference to trigger the reference rules -- if it can trigger UB when someone else holds a |
Are |
This discussion is only about So |
…twco Disallow reference to `static mut` and adding `static_mut_ref` lint Closes rust-lang#114447 r? `@scottmcm`
…twco Disallow reference to `static mut` and adding `static_mut_ref` lint Closes rust-lang#114447 r? `@scottmcm`
…twco Disallow reference to `static mut` and adding `static_mut_ref` lint Closes rust-lang#114447 r? ``@scottmcm``
Disallow reference to `static mut` and adding `static_mut_ref` lint Closes rust-lang#114447 r? `@scottmcm`
Going forward the way to use Though if you just need a "global" that's only used on a single thread there are still less "problematic" ways to do so, like using Box::leak to get a &'static mut T or Rc<RefCell> or similar. |
@est31 above mentioned the intention to deprecate The alternatives you suggested don't help when there is no way to pass the reference down the stack to where it will be needed. Also even if there is a way to pass the reference around, that's another Really we're all having to deal with bad decisions made when multi-threading was added to C. That is why there is all this mess. Single-thread per process is still a valid model, as is main-thread plus worker-threads. I wonder whether I'm the only person who cares about this. Maybe people assume that LLVM will take care of it, but it can't if things are fundamentally structured in a way that it can't optimise. There is a lot of talk of effects systems in Rust. Globals or thread-locals are a way to implement that, i.e. the need to get to a reference from deep down in the stack after passing through code which doesn't know anything about the "effect". So there still are valid uses. Maybe if someone wants to come up with a more restrictive formulation of |
Both of these things are true regardless of whether you are allowed to take reference to a Thread-ID checks and similar mechanisms can be built today using stable APIs on top of UnsafeCell, and don't need static mut. |
Note that I don't find this particularly persuasive, since as far as the linker sees, Is there something you're seeing that actually needs
Note that even if you only have one thread (and assume no interrupts) that's not enough on its own to make I would suggest people look at making some kind of safe library type to help this scenario. Perhaps comment in this zulip thread where I was trying to brainstorm something: https://rust-lang.zulipchat.com/#narrow/stream/327149-t-libs-api.2Fapi-changes/topic/static.20.60RefCell.60.20or.20single-threaded.20.60Mutex.60.3F/near/439487333.
If that's your concern you should comment in #53639. This issue is specifically about not completely deprecating it. |
Okay, I thought you were thinking of getting rid of mutable statics entirely. The 1.78 compiler warning which brought me to this page only mentioned |
That's exactly why we are only deprecating references to My personal opinion is that switching from |
Well, the simplest transition is to https://doc.rust-lang.org/std/cell/struct.SyncUnsafeCell.html, but unfortunately that's not yet stable :( You can always also make your own types with appropriate
The differences are in whether you get a reference directly. |
This is clearer now, thanks. I can see the justification for some kind of However, I couldn't use I don't think my new code is any better or worse without |
I feel this way too, and am glad that you do, too! Still, if there's some busywork to discourage misuse, I can live with that, just please let me have (the equivalent of) my: let p = ptr::addr_of_mut!(STATIC_MUT); There's programs I can't express without. For instance, we have a low-overhead profiler in our company that is just two rdtscs, and a couple of adds, loads and stores per profiling zone. The profiler is very careful to not create references, and it can only be ran in isolated single-threaded scenarios when we are tuning algorithms. |
With at least rustc 1.79.0 (129f3b996 2024-06-10) (Fedora 1.79.0-3.fc40) We were getting warnings when building the rust examples like warning: creating a mutable reference to mutable static is discouraged --> src/lib.rs:75:40 | 75 | let ctx: *mut luw_ctx_t = unsafe { &mut CTX }; | ^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 <rust-lang/rust#114447> = note: this will be a hard error in the 2024 edition = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | 75 | let ctx: *mut luw_ctx_t = unsafe { addr_of_mut!(CTX) }; | ~~~~~~~~~~~~~~~~~ So do like it says and use the addr_of_mut!() macro. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
As a reminder, the Rust issue tracker is for filing bugs or issues with the language, it is not for use as a helpdesk. This includes creating code of dubious quality via passing a random number generator through a filter (or vector of weights) and asking us to not lint on it: When lints trigger correctly, they are supposed to trigger on code of dubious quality, to discourage reusing it. |
fix for issue #114447 <rust-lang/rust#114447>
``` warning: creating a mutable reference to mutable static is discouraged --> src/main.rs:40:29 | 40 | unsafe { ALLOCATOR.init(&mut HEAP as *const u8 as usize, core::mem::size_of_val(&HEAP)) }; | ^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 <rust-lang/rust#114447> = note: this will be a hard error in the 2024 edition = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | 40 | unsafe { ALLOCATOR.init(addr_of_mut!(HEAP) as *const u8 as usize, core::mem::size_of_val(&HEAP)) }; | ~~~~~~~~~~~~~ + ```
``` warning: creating a mutable reference to mutable static is discouraged --> src/main.rs:40:29 | 40 | unsafe { ALLOCATOR.init(&mut HEAP as *const u8 as usize, core::mem::size_of_val(&HEAP)) }; | ^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 <rust-lang/rust#114447> = note: this will be a hard error in the 2024 edition = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | 40 | unsafe { ALLOCATOR.init(addr_of_mut!(HEAP) as *const u8 as usize, core::mem::size_of_val(&HEAP)) }; | ~~~~~~~~~~~~~ + ```
Summary: Fixes the following warning by following the advice given: ``` warning: creating a mutable reference to mutable static is discouraged --> fbcode/eden/scm/lib/cpython-ext/src/bytesobject.rs:37:13 | 37 | &mut PyBytes_Type as *mut PyTypeObject, | ^^^^^^^^^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 <rust-lang/rust#114447> = note: this will be a hard error in the 2024 edition = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | 37 | addr_of_mut!(PyBytes_Type) as *mut PyTypeObject, | ~~~~~~~~~~~~~ + ``` Reviewed By: quark-zju Differential Revision: D65218834 fbshipit-source-id: 8298cdf8089b6d8516e0cb59a811b30465eb1f8c
See rust-lang/rust#114447 for more information about the issue.
Now that we have
ptr::addr_of_mut!
, the 2024 edition would be a great time to do @RalfJung's idea from #53639 (comment):Disallow
&MY_STATIC_MUT
and&mut MY_STATIC_MUT
entirely.ptr::addr_of_mut!(MY_STATIC_MUT)
could even be safe -- unlike taking a reference which isunsafe
and often insta-UB -- and helps encourage avoiding races in the accesses, which is more practical than trying to avoid the UB from concurrent existence of references.(Maybe people will end up just doing
&mut *ptr::addr_of_mut!(MY_STATIC_MUT)
without thinking through all the safety requirements -- in particular, making sure that the reference stops being used before a second reference is created -- but we can't force them to drink.)The text was updated successfully, but these errors were encountered: