Skip to content

suggest mut removal sometimes for static mut ref lint/error #120574

Open
@est31

Description

@est31

Since #117556 we now lint for code like (playground):

use std::sync::atomic::AtomicI32;
use std::sync::Mutex;

static mut X: AtomicI32 = AtomicI32::new(1);

static mut Y: Mutex<usize> = Mutex::new(0);

fn foo() {
    unsafe {
        let _x = &X;
        let _y = &Y;
    }
}

gives:

warning: shared reference of mutable static is discouraged
  --> src/lib.rs:12:18
   |
12 |         let _x = &X;
   |                  ^^ shared reference of mutable static
   |
   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: reference of mutable static is a hard error from 2024 edition
   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
   = note: `#[warn(static_mut_ref)]` on by default
help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
   |
12 |         let _x = addr_of!(X);
   |                  ~~~~~~~~~~~

warning: shared reference of mutable static is discouraged
  --> src/lib.rs:13:18
   |
13 |         let _y = &Y;
   |                  ^^ shared reference of mutable static
   |
   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: reference of mutable static is a hard error from 2024 edition
   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
   |
13 |         let _y = addr_of!(Y);
   |                  ~~~~~~~~~~~

It suggests using addr_of which is correct but it requires unsafe and we actually don't need it: we can just remove the mut here:

use std::sync::atomic::AtomicI32;
use std::sync::Mutex;

static X: AtomicI32 = AtomicI32::new(1);

static Y: Mutex<usize> = Mutex::new(0);

fn foo() {
    unsafe {
        let _x = &X;
        let _y = &Y;
    }
}

The lint message (error in 2024 edition) should suggest such removal of mut where possible.

The tough part is to find out where this is actually possible. With the right wording we might get away with a heuristic that doesn't recognize all cases correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lints

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions