-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Open
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.Category: This is a bug.I-prioritizeIssue: Indicates that prioritization has been requested for this issue.Issue: Indicates that prioritization has been requested for this issue.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.Performance or correctness regression from stable to beta.
Description
Code
#![feature(thread_local)]
use std::cell::UnsafeCell;
use std::ops::Deref;
use std::ptr::NonNull;
use std::cell::Cell;
pub struct LocalKey<T> {
inner: fn(Option<&mut Option<T>>) -> NonNull<T>,
}
impl<T: 'static> LocalKey<T> {
#[doc(hidden)]
pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> NonNull<T>) -> Self {
Self { inner }
}
}
// stdlib's LocalKey does not implement Deref, this seems to be the difference
impl<T> Deref for LocalKey<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { (self.inner)(None).as_ref() }
}
}
// Inlined, cut-down version similar to the output of thread_local
const LOCAL_COUNT: LocalKey<Cell<usize>> = {
#[inline]
fn __init() -> Cell<usize> {
Cell::new(0)
}
unsafe {
LocalKey::new(const {
|_| {
#[thread_local]
static VAL: UnsafeCell<Option<Cell<usize>>> = UnsafeCell::new(None);
NonNull::from((*VAL.get()).get_or_insert_with(__init))
}
})
}
};
fn main() {
let count = LOCAL_COUNT.get();
LOCAL_COUNT.set(count);
}Current output
Compiling playground v0.0.1 (/playground)
warning: mutation of an interior mutable `const` item with call to `get`
--> src/main.rs:48:17
|
48 | let count = LOCAL_COUNT.get();
| -----------^^^^^^
| |
| `LOCAL_COUNT` is a interior mutable `const` item of type `LocalKey<Cell<usize>>`
|
= note: each usage of a `const` item creates a new temporary
= note: only the temporaries and never the original `const LOCAL_COUNT` will be modified
= help: for more details on interior mutability see <https://doc.rust-lang.org/reference/interior-mutability.html>
= note: `#[warn(const_item_interior_mutations)]` on by default
help: for a shared instance of `LOCAL_COUNT`, consider making it a `static` item instead
|
29 - const LOCAL_COUNT: LocalKey<Cell<usize>> = {
29 + static LOCAL_COUNT: LocalKey<Cell<usize>> = {
|
warning: mutation of an interior mutable `const` item with call to `set`
--> src/main.rs:49:5
|
49 | LOCAL_COUNT.set(count);
| -----------^^^^^^^^^^^
| |
| `LOCAL_COUNT` is a interior mutable `const` item of type `LocalKey<Cell<usize>>`
|
= note: each usage of a `const` item creates a new temporary
= note: only the temporaries and never the original `const LOCAL_COUNT` will be modified
= help: for more details on interior mutability see <https://doc.rust-lang.org/reference/interior-mutability.html>
help: for a shared instance of `LOCAL_COUNT`, consider making it a `static` item instead
|
29 - const LOCAL_COUNT: LocalKey<Cell<usize>> = {
29 + static LOCAL_COUNT: LocalKey<Cell<usize>> = {
|
warning: `playground` (bin "playground") generated 2 warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.66s
Running `target/debug/playground`Desired output
Not thatRationale and extra context
See a playground reproduction: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=ffb22b5b2cc4581b16463e46891b438e
Which is a cut down reproduction of a cpu-local storage primitive crate I'm maintaining (which is a simplified, no_std version of stdlibs thread_local).
The type is LocalKey<Cell<usize>> yes, but it is not actually interior-ly (?) mutable, it is just a function pointer to the actually interior mutable thread-local static (which is a static so all good). This seems to be a case where #148407 does not infer the type correctly?
Other cases
Rust Version
rustc 1.94.0-nightly (f52090008 2025-12-10)
binary: rustc
commit-hash: f5209000832c9d3bc29c91f4daef4ca9f28dc797
commit-date: 2025-12-10
host: aarch64-apple-darwin
release: 1.94.0-nightly
LLVM version: 21.1.5Anything else?
No response
Metadata
Metadata
Assignees
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.Category: This is a bug.I-prioritizeIssue: Indicates that prioritization has been requested for this issue.Issue: Indicates that prioritization has been requested for this issue.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.Performance or correctness regression from stable to beta.