# Deprecate static mut (in the next edition?)

**URL:** <https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975>\
**Category:** language design\
**Created:** [December 4, 2023, 2:31pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975 "2023-12-04T14:31:23Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [December 4, 2023, 2:31pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/1 "2023-12-04T14:31:23Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Xanewok](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xanewok/32/2305_2.png) [@Xanewok](https://internals.rust-lang.org/u/Xanewok)\
**Post date:** [December 4, 2023, 2:53pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/2 "2023-12-04T14:53:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [December 4, 2023, 2:54pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/3 "2023-12-04T14:54:35Z")

</div>

> [@kornel](#):
>
> use `Mutex`/`OnceCell`/`UnsafeCell` instead

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

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [December 5, 2023, 12:07am UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/4 "2023-12-05T00:07:36Z")

</div>

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. 😬 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<..>`

---

<div class="post-metadata">

**Author:** ![ohAitch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ohaitch/32/5779_2.png) [@ohAitch](https://internals.rust-lang.org/u/ohAitch)\
**Post date:** [December 6, 2023, 7:48pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/5 "2023-12-06T19:48:42Z")

</div>

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`?

---

<div class="post-metadata">

**Author:** ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)\
**Post date:** [December 6, 2023, 8:03pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/6 "2023-12-06T20:03:11Z")

</div>

> [@ohAitch](#):
>
> has RacyUnsafeCell been stabilized? Alternately, did regular UnsafeCell turn out to cover all existing embedded etc uses if `static mut`?

It got renamed.

> <https://github.com/rust-lang/rust/issues/95439>
>
> Feature gate: \`#!\[feature(sync\_unsafe\_cell)\]\`
> 
> This is a tracking issue for Sy…ncUnsafeCell.
> \### Public API
> 
> \`\`\`rust
> // core::cell
> 
> \#\[repr(transparent)\]
> pub struct SyncUnsafeCell\<T: ?Sized\> {
> value: UnsafeCell\<T\>,
> }
> 
> unsafe impl\<T: ?Sized + Sync\> Sync for SyncUnsafeCell\<T\> {}
> 
> // Identical interface as UnsafeCell:
> 
> impl\<T\> SyncUnsafeCell\<T\> {
> pub const fn new(value: T) -\> Self;
> pub const fn into\_inner(self) -\> T;
> }
> 
> impl\<T: ?Sized\> SyncUnsafeCell\<T\> {
> pub const fn get(&self) -\> \*mut T;
> pub const fn get\_mut(&mut self) -\> &mut T;
> pub const fn raw\_get(this: \*const Self) -\> \*mut T;
> }
> 
> impl\<T\> From\<T\> for SyncUnsafeCell\<T\>;
> impl\<T: Default\> Default for SyncUnsafeCell\<T\>;
> impl\<T: ?Sized\> Debug for SyncUnsafeCell\<T\>;
> \`\`\`
> 
> \### Steps / History
> 
> \<!--
> For larger features, more steps might be involved.
> If the feature is changed later, please add those PRs here as well.
> \--\>
> 
> \- \[x\] Implementation: https://github.com/rust-lang/rust/pull/95438
> \- \[\] Final comment period (FCP)
> \- \[\] Stabilization PR
> 
> \### Unresolved Questions
> 
> \- Name: SyncUnsafeCell? RacyUnsafeCell? RacyCell? UnsafeSyncCell? ..?
> \- Should it be \`Sync\` only if \`T\` is \`Sync\`, or should it unconditionally be \`Sync\`?

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [December 6, 2023, 9:36pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/7 "2023-12-06T21:36:46Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [December 6, 2023, 11:38pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/8 "2023-12-06T23:38:09Z")

</div>

How about `deny` for references and `warn` for any usage?

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [December 7, 2023, 12:05am UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/9 "2023-12-07T00:05:58Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [December 7, 2023, 1:09am UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/10 "2023-12-07T01:09:52Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)\
**Post date:** [December 7, 2023, 1:38am UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/11 "2023-12-07T01:38:06Z")

</div>

> [@pitaj](#):
>
> How about `deny` for references and `warn` for any usage?

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?

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [December 7, 2023, 8:20pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/12 "2023-12-07T20:20:01Z")

</div>

> [@pitaj](#):
>
> and `warn` for any usage?

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.

> [@kornel](#):
>
> So jumping immediately to deny would be skipping a step.

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.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 6, 2024, 8:20pm UTC](https://internals.rust-lang.org/t/deprecate-static-mut-in-the-next-edition/19975/13 "2024-03-06T20:20:18Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
