Email me

Clippy lints / Style

Clippy lint · Style · checked with Clippy 0.1.99

clippy::borrow_interior_mutable_const: borrow of a named constant with interior mutability

What it meansChecks for a borrow of a named constant with interior mutability. It is in the style group and warns by default.

What you see

warning: borrow of a named constant with interior mutability
 --> main.rs:8:5
  |
8 |     ATOMIC.fetch_add(1, Ordering::AcqRel)
  |     ^^^^^^
  |
  = note: there is a compiler inserted borrow here
  = help: this lint can be silenced by assigning the value to a local variable before borrowing
  = help: for further information visit https://rust-lang.github.io/rust-clippy/stable/index.html#borrow_interior_mutable_const
  = note: `#[warn(clippy::borrow_interior_mutable_const)]` on by default

Real output of Clippy 0.1.99 (Rust 1.99) on the example below. Names and line numbers in yours will differ.

Does it matter?

Named constants are copied at every use site which means any change to their value will be lost after the newly created value is dropped. e.g. use core::sync::atomic::{AtomicUsize, Ordering}; const ATOMIC: AtomicUsize = AtomicUsize::new(0); fn add_one() -> usize { // This will always return `0` since `ATOMIC` is copied before it's borrowed // for use by `fetch_add`. ATOMIC.fetch_add(1, Ordering::AcqRel) }

Code that works but is not idiomatic Rust. Warns by default.

How to fix it

Clippy does not fix this one automatically. Change the code by hand:

Flagged

use core::sync::atomic::{AtomicUsize, Ordering};
const ATOMIC: AtomicUsize = AtomicUsize::new(0);
fn add_one() -> usize {
    // This will always return `0` since `ATOMIC` is copied before it's borrowed
    // for use by `fetch_add`.
    ATOMIC.fetch_add(1, Ordering::AcqRel)
}

Write this instead

use core::cell::Cell;
const CELL: Cell<usize> = Cell::new(0);
fn get_cell() -> Cell<usize> {
    // This is fine. It borrows a copy of `CELL`, but never mutates it through the
    // borrow.
    CELL.clone()
}

Turn it off, or on

Allow it where it does not fit your code, as narrowly as you can:

On one item

#[allow(clippy::borrow_interior_mutable_const)]
fn my_function() { /* ... */ }

Whole crate (Cargo.toml)

[lints.clippy]
borrow_interior_mutable_const = "allow"

One run

cargo clippy -- -A clippy::borrow-interior-mutable-const

The [lints] table needs Rust 1.74 or newer. In a workspace, put it under [workspace.lints.clippy] and add [lints] workspace = true to each member.

Settings in clippy.toml

  • ignore-interior-mutability: A list of paths to types that should be treated as if they do not contain interior mutability
Stylegroup
warndefault level
nofixed by cargo clippy --fix
pre 1.29.0added in Rust

Clippy's own documentation

What it does

Checks for a borrow of a named constant with interior mutability.

Why is this bad?

Named constants are copied at every use site which means any change to their value will be lost after the newly created value is dropped. e.g.

use core::sync::atomic::{AtomicUsize, Ordering};
const ATOMIC: AtomicUsize = AtomicUsize::new(0);
fn add_one() -> usize {
    // This will always return `0` since `ATOMIC` is copied before it's borrowed
    // for use by `fetch_add`.
    ATOMIC.fetch_add(1, Ordering::AcqRel)
}

Known problems

This lint does not, and cannot in general, determine if the borrow of the constant is used in a way which causes a mutation. e.g.

use core::cell::Cell;
const CELL: Cell<usize> = Cell::new(0);
fn get_cell() -> Cell<usize> {
    // This is fine. It borrows a copy of `CELL`, but never mutates it through the
    // borrow.
    CELL.clone()
}

There also exists types which contain private fields with interior mutability, but no way to both create a value as a constant and modify any mutable field using the type’s public interface (e.g. bytes::Bytes). As there is no reasonable way to scan a crate’s interface to see if this is the case, all such types will be linted. If this happens use the ignore-interior-mutability configuration option to allow the type.

Example

use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);

CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct

Use instead:

use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);

static STATIC_ATOM: AtomicUsize = CONST_ATOM;
STATIC_ATOM.store(9, SeqCst);
assert_eq!(STATIC_ATOM.load(SeqCst), 9); // use a `static` item to refer to the same instance

Configuration

  • ignore-interior-mutability: A list of paths to types that should be treated as if they do not contain interior mutability

    (default: ["bytes::Bytes"])

From the Clippy lint list (0.1.99), part of the Rust project, MIT or Apache-2.0. Official entry.

Related lints

All 847 Clippy lints · Rust compiler errors · Cargo.toml checker

Up next

Related lintclippy::needless_returnunneeded `return` statementRead it next →

Did this answer your question?

Get the receipts by email.

What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.

No spam, never sold. Every email has a one-click unsubscribe.

Popular in the shop

All 124 tools →

Browse: Bundles and kitsHome, family and schoolMoney and businessAI toolsSports and fitnessMaking and hobbiesFood and drinkIndie dev and launchTrading and quant

Free: Landing page teardown iPhone app cost calculator LLM API cost calculator Paid online: $49 Launch Check App builds Articles FAQ