Skip to content

Add lint against (some) interior mutable consts#132146

Closed
Urgau wants to merge 6 commits intorust-lang:masterfrom
Urgau:interior_mut_consts
Closed

Add lint against (some) interior mutable consts#132146
Urgau wants to merge 6 commits intorust-lang:masterfrom
Urgau:interior_mut_consts

Conversation

@Urgau
Copy link
Member

@Urgau Urgau commented Oct 25, 2024

interior_mutable_consts

warn-by-default

The interior_mutable_consts lint detects instance where const-items have a interior mutable type, which silently does nothing.

Example

use std::sync::Once;

// SAFETY: should only be call once
unsafe extern "C" fn ffi_init() { /* ... */ }

const A: Once = Once::new(); // using `A` will always creates temporaries and
                             // never modify it-self on use, should be a
                             // static-item instead

fn init() {
    A.call_once(|| unsafe {
        ffi_init();  // unsound, as the `call_once` is on a temporary
                     // and not on a shared variable
    })
}
warning: interior mutability in `const` items have no effect on the `const` item itself
  --> $DIR/interior-mutable-types-in-consts.rs:8:1
   |
LL | const A: Once = Once::new();
   | ^^^^^^^^^----^^^^^^^^^^^^^^^
   |          |
   |          `Once` is an interior mutable type
   |
   = note: each usage of a `const` item creates a new temporary
   = note: only the temporaries and never the original `const` item `A` will be modified
   = help: for use as an initializer, consider using an inline-const `const { /* ... */ }` at the usage site instead
   = note: `#[warn(interior_mutable_consts)]` on by default
help: for a shared instance of `A`, consider using a `static` item instead
   |
LL - const A: Once = Once::new();
LL + static A: Once = Once::new();
   |
help: alternatively consider expecting the lint
   |
LL | #[expect(interior_mutable_consts, reason = "...")] const A: Once = Once::new();
   | ++++++++++++++++++++++++++++++++++++++++++++++++++

Explanation

Using a const-item with an interior mutable type has no effect as const-item are essentially inlined wherever they are used, meaning that they are copied directly into the relevant context when used rendering modification through interior mutability ineffective across usage of that const-item.

The current implementation of this lint only warns on significant std and core interior mutable types, like Once, AtomicI32, ... this is done out of prudence and may be extended in the future.


It should be noted that the lint in not immunized against false-positives in particular when those immutable const-items are used as "init" const for const arrays (i.e. [INIT; 10]), which is why the lint recommends inline-const instead.

It should also be noted that this is NOT an uplift of the more general clippy::declare_interior_mutable_const lint, which works for all interior mutable types, but has even more false-positives than the currently proposed lint.

A simple Github Search reveals many instance where the user probably wanted to use a static-item instead.


@rustbot labels +I-lang-nominated +T-lang -S-waiting-on-review
cc @AngelicosPhosphoros @kupiakos
r? compiler

Fixes IRLO - Forbidding creation of constant mutexes, etc
Fixes #132028
Fixes #40543

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Silent failure of std::sync::Once when in const variable Produce a warning when using const with interior mutability