Deprecate static mut (in the next edition?)

AFAIK static mut was a bad idea, and shouldn't be a language feature. It could have been regular static with UnsafeCell or some other interior mutability type.

Currently it mainly serves as a trap for novice users who want to make a mutable global variable, or follow compiler's advice of "needs to live for a 'static lifetime", and end up with a wrong solution.

So how about making static mut trigger a deprecation warning with a message along the lines of "use Mutex/OnceCell/UnsafeCell instead"?

Of course the warning could be silenced with #[allow(deprecated)], so whoever really really wants to use static mut can continue to do so.

19 Likes

For what it's worth, there's already https://github.com/rust-lang/rust/issues/53639 and Disallow *references* to `static mut` [Edition Idea] · Issue #114447 · rust-lang/rust · GitHub that is tracking/discussing that.

Probably OnceLock, and SyncUnsafeCell here (if the latter gets stabilized); otherwise there’s an error for missing Sync implementation.

6 Likes

Please. Please please please. I still see programmers coming from C/C++ just casually throw down a static mut as they're trying out rust, and the shriek of terror that escapes my mouth each time does nothing to stop the next person from doing the same.

I've even seen people try to use it for inter-thread communication. :grimacing: Worse, sometimes it works.

I found this reddit comment by @Manishearth:

A macro that does the cell shenanigans for you would be nice. In fact that's what static mut should have been: sugar for static ..: UnsafeCell<..>

15 Likes

A notable comment from the first thread is

As for FFI, UnsafeCell and RacyUnsafeCell should be #[repr(transparent)] , meaning that extern { static X: RacyUnsafeCell<T>; } should work as well as extern { static mut X: T } .

has RacyUnsafeCell been stabilized? Alternately, did regular UnsafeCell turn out to cover all existing embedded etc uses if static mut?

It got renamed.

2 Likes

The possibility of deprecating static mut entirely came up (very briefly) in a lang meeting today, actually.

The currently-in-the-works change to disallow references to static mut should substantially help push people away from at least the most UB parts of it, and hopefully to better things like SyncUnsafeCell or their own wrapper type.

(For example, that's enough to ensure that the "casually throw down" folks that ExpHP mentioned will at least get a warning pushing them away from it.)

My current thought is that that might be enough for 2024. I don't know that we should deprecate it entirely for 2024 -- maybe it's fine to do the partial thing for now then reevaluate how we feel in 2026 to consider a change in 2027.

Push-back welcome.

7 Likes

How about deny for references and warn for any usage?

Code building without any warnings in one edition is supposed to continue working in the next edition. The procedure is warn first, deny in the next edition. So jumping immediately to deny would be skipping a step.

Right, but we're working on that reference point right now, so we could land it as a warning right away.

This combination specifically just seems like making extra noise/warnings for the same issue. Generally you should only have to check "I have read the terms and conditions" once.

SyncUnsafeCell solves my specific use case for static mut. It would be nice to have that stabilized before we issue a hard error, but a warning before that seems fine: it can be silenced on stable and SyncUnsafeCell can be used on nightly. Are there use cases of static mut that aren't covered by that type?

4 Likes

I'm generally opposed to any sort of "whenever you use this language feature at all you get a warning" plan.

This regularly comes up related to floats, for example, around things like warning about x == 0.0. And yes, there's gotchas about that, but it's also possibly the right thing. So I really don't want a lint that basically becomes #![allow(yes_i_know_that_i_am_using_floats)].

I think "there's a better way that you should write this instead" warnings are usually a better fit for more opinionated tools -- rustc usually oughtn't bother you if you're doing something fine, even if it's something not great, at least for things that are internal to your crate. That helps encourage people to take seriously the warnings they do get.

Though certainly the line between "not great" and "error-prone" is often fuzzy.

Jumping to deny inside an edition is allowed, just not to error. Though it's certainly rare, because things we feel strongly enough to deny in rustc are uncommon.

2 Likes