Skip to content

Consider deprecation of UB-happy static mut #53639

Not planned
@eddyb

Description

@eddyb
Member

static mut is almost impossible to use correctly, see rust-lang-nursery/lazy-static.rs#117 for an example in the widely-used lazy-static.

You must be able to show that every borrow of the static mut is not reentrant (as opposed to regular interior mutability, which only requires reentrance-freedom when accessing data), which is almost entirely impossible in real-world scenarios.


We have a chance at removing it from Rust2018 and force people to use a proper synchronization abstraction (e.g. lazy_static! + Mutex), or in lieu of one, thread_local! / scoped_thread_local!.

If they were using static mut with custom synchronization logic, they should do this:

pub struct CustomSynchronizingAbstraction<T> {
    /* UnsafeCell / Cell / RefCell / etc. around data, e.g. `T` */
}
// Promise that proper synchronization exists *around accesses*.
unsafe impl<T: Sync> Sync for CustomSynchronizingAbstraction<T> {}

And then use CustomSynchronizingAbstraction with regular statics, safely.

This matches the "soundness boundary" of Rust APIs, whereas static mut is more like C.

cc @RalfJung @rust-lang/compiler @rust-lang/lang


2023-08 Note from triage, many years later: there's now https://doc.rust-lang.org/1.71.0/std/cell/struct.SyncUnsafeCell.html in the library, added by #95438, which can be used instead of static mut. But static mut is not even soft-deprecated currently.

Activity

Centril

Centril commented on Aug 23, 2018

@Centril
Contributor

I don't know at all whether we should do this or not atm. But to make this decision I have an...

...Idea: We should do a crater run to scrutinize how many legitimate usages there are and how many ones there are that have UB.

nikomatsakis

nikomatsakis commented on Aug 23, 2018

@nikomatsakis
Contributor

cc @rust-lang/wg-unsafe-code-guidelines -- we have this group just for this sort of thing =)

alercah

alercah commented on Aug 23, 2018

@alercah
Contributor

I'm 100% behind getting rid of static mut. Any attempt to use it which isn't UB is replaceable with something else which is safe, likely a Mutex or something thread local. Or, per the original comment, a custom alternate type implementing Sync directly.

joshtriplett

joshtriplett commented on Aug 23, 2018

@joshtriplett
Member

We should clearly document the undefined behavior, but I don't think we should remove the ability to have (unsafe) global mutable locations directly, without any layer of indirection. That would make it more difficult to build certain types of lock-free synchronization, for instance.

eddyb

eddyb commented on Aug 23, 2018

@eddyb
MemberAuthor

@joshtriplett But you can always use unsafe impl Sync + static?

alercah

alercah commented on Aug 23, 2018

@alercah
Contributor

Can you give an example of what you mean? You can't do much more with static mut than you could with a static UnsafeCell.

RalfJung

RalfJung commented on Aug 23, 2018

@RalfJung
Member

But you can always use unsafe impl Sync + static?

Yeah, and that's just as unsafe. So TBH I do not see the point.

eddyb

eddyb commented on Aug 23, 2018

@eddyb
MemberAuthor

@RalfJung No, it's not, and I've explained why. With unsafe impl Sync, you only have to prove the data accesses correct, but with static mut, the references themselves can conflict.

EDIT: Now if "references exist" cannot be UB, ever, then this is not a problem, but IIUC, they do.
Also, you can't use a static mut from safe code, only a static. If the static mut is used correctly, why spread unsafety when you can wrap it in a sound API.

alercah

alercah commented on Aug 23, 2018

@alercah
Contributor

It's not actually different from an UnsafeCell if we replace each &var with unsafe {&*var.get()}, right? Then the aliasing rules would be the same; the difference is that with the UnsafeCell you can still keep references to the cell itself?

RalfJung

RalfJung commented on Aug 23, 2018

@RalfJung
Member

@eddyb Ah okay I see -- that has nothing to with with unsafe impl tough and everything with &UnsafeCell.

I agree &UnsafeCell is safer than static mut.

eddyb

eddyb commented on Aug 23, 2018

@eddyb
MemberAuthor

@RalfJung Okay I should make it clearer that the unsafe impl is for "custom synchronization abstraction". I'll go edit the issue description.

RalfJung

RalfJung commented on Aug 23, 2018

@RalfJung
Member

If we could weaken static mut to only give you raw pointers, that could help...

... tough people would probably still turn them into references ASAP.

japaric

japaric commented on Aug 23, 2018

@japaric
Member

If they were using static mut with custom synchronization logic, they should do this:

How would they instantiate their custom type in stable Rust? User cons fns are unstable and even if we do stabilize min_const_fn that doesn't include anything that has bounds so even with that your example won't compile on stable.

To me this sounds like it would reduce what you can do in the 2018 edition. In the 2015 edition you can create static mut variables that contain primitive types but in the 2018 edition you can not do the equivalent unless I'm missing something like adding a RacyCell type with const constructor to core. (Here I'm assuming that it's not certain whether min_const_fn will make it into the edition release).

299 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-maybe-future-editionSomething we may consider for a future edition.C-enhancementCategory: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchT-langRelevant to the language teamdisposition-closeThis PR / issue is in PFCP or FCP with a disposition to close it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.needs-rfcThis change is large or controversial enough that it should have an RFC accepted before doing it.

    Type

    No type

    Projects

    Status

    Rejected/Not lang

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @briansmith@ehuss@comex@whitequark@alexreg

        Issue actions

          Consider deprecation of UB-happy `static mut` · Issue #53639 · rust-lang/rust