Skip to content

make atomic operations const - #160079

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
RalfJung:const-atomic
Aug 1, 2026
Merged

make atomic operations const#160079
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
RalfJung:const-atomic

Conversation

@RalfJung

@RalfJung RalfJung commented Jul 28, 2026

Copy link
Copy Markdown
Member

In a similar vein to #159094, it makes sense to make these const fn so that code can be shared between compile-time and run-time even if the runtime version has to deal with concurrency.

This constifies the following:

// core::sync::atomic

impl AtomicBool {
    pub const fn get_mut(&mut self) -> &mut bool;
    pub const fn from_mut(v: &mut bool) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [bool];
    pub const fn from_mut_slice(v: &mut [bool]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> bool;
    pub const fn store(&self, val: bool, order: Ordering);
    pub const fn swap(&self, val: bool, order: Ordering) -> bool;
    pub const fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool;
    pub const fn compare_exchange(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn compare_exchange_weak(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn fetch_and(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_nand(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_or(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_xor(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_not(&self, order: Ordering) -> bool;
}

impl AtomicPtr<T> {
    pub const fn get_mut(&mut self) -> &mut *mut T;
    pub const fn from_mut(v: &mut *mut T) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T];
    pub const fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> *mut T;
    pub const fn store(&self, ptr: *mut T, order: Ordering);
    pub const fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T;
}

impl Atomic$Int {
    pub const fn get_mut(&mut self) -> &mut $int_type;
    pub const fn from_mut(v: &mut $int_type) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type];
    pub const fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> $int_type;
    pub const fn store(&self, val: $int_type, order: Ordering);
    pub const fn swap(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn compare_and_swap(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    order: Ordering) -> $int_type;
    pub const fn compare_exchange(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    success: Ordering,
                                    failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn compare_exchange_weak(&self,
                                         current: $int_type,
                                         new: $int_type,
                                         success: Ordering,
                                         failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type;
}

pub const fn fence(order: Ordering);
pub const fn compiler_fence(order: Ordering);

However, this excludes the fetch_* and compare_* operations on AtomicPtr, as that kind of pointer arithmetic is not possible at compile time.

Tracking issue: #160078
Cc @rust-lang/wg-const-eval @rust-lang/opsem

@rustbot

rustbot commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @oli-obk, @lcnr

miri is developed in its own repository. If the Miri part of this change can be broken out, consider making this change to rust-lang/miri instead. However, if Miri needs adjusting for rustc changes, just ignore this message.

cc @rust-lang/miri

Some changes occurred to the CTFE machinery

cc @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 28, 2026
@rustbot

rustbot commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

r? @folkertdev

rustbot has assigned @folkertdev.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler, mir
  • compiler, mir expanded to 74 candidates
  • Random selection from 16 candidates

@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rust-bors

rust-bors Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

📌 Commit aa1b09a has been approved by folkertdev

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 31, 2026
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 1, 2026
make atomic operations const

In a similar vein to rust-lang#159094, it makes sense to make these `const fn` so that code can be shared between compile-time and run-time even if the runtime version has to deal with concurrency.

This constifies the following:
```rust
// core::sync::atomic

impl AtomicBool {
    pub const fn get_mut(&mut self) -> &mut bool;
    pub const fn from_mut(v: &mut bool) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [bool];
    pub const fn from_mut_slice(v: &mut [bool]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> bool;
    pub const fn store(&self, val: bool, order: Ordering);
    pub const fn swap(&self, val: bool, order: Ordering) -> bool;
    pub const fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool;
    pub const fn compare_exchange(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn compare_exchange_weak(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn fetch_and(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_nand(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_or(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_xor(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_not(&self, order: Ordering) -> bool;
}

impl AtomicPtr<T> {
    pub const fn get_mut(&mut self) -> &mut *mut T;
    pub const fn from_mut(v: &mut *mut T) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T];
    pub const fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> *mut T;
    pub const fn store(&self, ptr: *mut T, order: Ordering);
    pub const fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T;
}

impl Atomic$Int {
    pub const fn get_mut(&mut self) -> &mut $int_type;
    pub const fn from_mut(v: &mut $int_type) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type];
    pub const fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> $int_type;
    pub const fn store(&self, val: $int_type, order: Ordering);
    pub const fn swap(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn compare_and_swap(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    order: Ordering) -> $int_type;
    pub const fn compare_exchange(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    success: Ordering,
                                    failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn compare_exchange_weak(&self,
                                         current: $int_type,
                                         new: $int_type,
                                         success: Ordering,
                                         failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type;
}

pub const fn fence(order: Ordering);
pub const fn compiler_fence(order: Ordering);
```

However, this excludes the `fetch_*` and `compare_*` operations on `AtomicPtr`, as that kind of pointer arithmetic is not possible at compile time.

Tracking issue: rust-lang#160078
Cc @rust-lang/wg-const-eval @rust-lang/opsem
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 1, 2026
make atomic operations const

In a similar vein to rust-lang#159094, it makes sense to make these `const fn` so that code can be shared between compile-time and run-time even if the runtime version has to deal with concurrency.

This constifies the following:
```rust
// core::sync::atomic

impl AtomicBool {
    pub const fn get_mut(&mut self) -> &mut bool;
    pub const fn from_mut(v: &mut bool) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [bool];
    pub const fn from_mut_slice(v: &mut [bool]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> bool;
    pub const fn store(&self, val: bool, order: Ordering);
    pub const fn swap(&self, val: bool, order: Ordering) -> bool;
    pub const fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool;
    pub const fn compare_exchange(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn compare_exchange_weak(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn fetch_and(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_nand(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_or(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_xor(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_not(&self, order: Ordering) -> bool;
}

impl AtomicPtr<T> {
    pub const fn get_mut(&mut self) -> &mut *mut T;
    pub const fn from_mut(v: &mut *mut T) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T];
    pub const fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> *mut T;
    pub const fn store(&self, ptr: *mut T, order: Ordering);
    pub const fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T;
}

impl Atomic$Int {
    pub const fn get_mut(&mut self) -> &mut $int_type;
    pub const fn from_mut(v: &mut $int_type) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type];
    pub const fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> $int_type;
    pub const fn store(&self, val: $int_type, order: Ordering);
    pub const fn swap(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn compare_and_swap(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    order: Ordering) -> $int_type;
    pub const fn compare_exchange(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    success: Ordering,
                                    failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn compare_exchange_weak(&self,
                                         current: $int_type,
                                         new: $int_type,
                                         success: Ordering,
                                         failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type;
}

pub const fn fence(order: Ordering);
pub const fn compiler_fence(order: Ordering);
```

However, this excludes the `fetch_*` and `compare_*` operations on `AtomicPtr`, as that kind of pointer arithmetic is not possible at compile time.

Tracking issue: rust-lang#160078
Cc @rust-lang/wg-const-eval @rust-lang/opsem
rust-bors Bot pushed a commit that referenced this pull request Aug 1, 2026
Rollup of 14 pull requests

Successful merges:

 - #159245 (Emit retags in codegen to support BorrowSanitizer (part 5))
 - #159864 (Report "capacity overflow" for oversized Rc<[T]>/Arc<[T]>)
 - #160079 (make atomic operations const)
 - #160124 (Structurally prevent zero-count `BackendRepr::SimdVector`s)
 - #160162 (Make `#[fundamental]` only apply to the first argument of `Box`)
 - #160210 (Remove an outdated FIXME)
 - #160282 (Improve diagnostic for patterns in function pointer types)
 - #157928 (Eagerly fetch typeck results when linting)
 - #159672 (Improve suggestions when multiples tuples implement the same trait)
 - #159861 (Add documentation for the `non_exhaustive` attribute)
 - #159907 (Fix `hidden_glob_reexports` in `rustc_ast`)
 - #159998 (Align expect messages with guidance)
 - #160145 (Expand checks for register_tool)
 - #160307 (Update `minifier` version to `0.4.0`)
@rust-bors
rust-bors Bot merged commit f5811a1 into rust-lang:main Aug 1, 2026
13 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Aug 1, 2026
rust-timer added a commit that referenced this pull request Aug 1, 2026
Rollup merge of #160079 - RalfJung:const-atomic, r=folkertdev

make atomic operations const

In a similar vein to #159094, it makes sense to make these `const fn` so that code can be shared between compile-time and run-time even if the runtime version has to deal with concurrency.

This constifies the following:
```rust
// core::sync::atomic

impl AtomicBool {
    pub const fn get_mut(&mut self) -> &mut bool;
    pub const fn from_mut(v: &mut bool) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [bool];
    pub const fn from_mut_slice(v: &mut [bool]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> bool;
    pub const fn store(&self, val: bool, order: Ordering);
    pub const fn swap(&self, val: bool, order: Ordering) -> bool;
    pub const fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool;
    pub const fn compare_exchange(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn compare_exchange_weak(
        &self,
        current: bool,
        new: bool,
        success: Ordering,
        failure: Ordering,
    ) -> Result<bool, bool>;
    pub const fn fetch_and(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_nand(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_or(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_xor(&self, val: bool, order: Ordering) -> bool;
    pub const fn fetch_not(&self, order: Ordering) -> bool;
}

impl AtomicPtr<T> {
    pub const fn get_mut(&mut self) -> &mut *mut T;
    pub const fn from_mut(v: &mut *mut T) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T];
    pub const fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> *mut T;
    pub const fn store(&self, ptr: *mut T, order: Ordering);
    pub const fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T;
}

impl Atomic$Int {
    pub const fn get_mut(&mut self) -> &mut $int_type;
    pub const fn from_mut(v: &mut $int_type) -> &mut Self;
    pub const fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type];
    pub const fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self];
    pub const fn load(&self, order: Ordering) -> $int_type;
    pub const fn store(&self, val: $int_type, order: Ordering);
    pub const fn swap(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn compare_and_swap(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    order: Ordering) -> $int_type;
    pub const fn compare_exchange(&self,
                                    current: $int_type,
                                    new: $int_type,
                                    success: Ordering,
                                    failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn compare_exchange_weak(&self,
                                         current: $int_type,
                                         new: $int_type,
                                         success: Ordering,
                                         failure: Ordering) -> Result<$int_type, $int_type>;
    pub const fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type;
    pub const fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type;
}

pub const fn fence(order: Ordering);
pub const fn compiler_fence(order: Ordering);
```

However, this excludes the `fetch_*` and `compare_*` operations on `AtomicPtr`, as that kind of pointer arithmetic is not possible at compile time.

Tracking issue: #160078
Cc @rust-lang/wg-const-eval @rust-lang/opsem
pull Bot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Aug 2, 2026
Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#159245 (Emit retags in codegen to support BorrowSanitizer (part 5))
 - rust-lang/rust#159864 (Report "capacity overflow" for oversized Rc<[T]>/Arc<[T]>)
 - rust-lang/rust#160079 (make atomic operations const)
 - rust-lang/rust#160124 (Structurally prevent zero-count `BackendRepr::SimdVector`s)
 - rust-lang/rust#160162 (Make `#[fundamental]` only apply to the first argument of `Box`)
 - rust-lang/rust#160210 (Remove an outdated FIXME)
 - rust-lang/rust#160282 (Improve diagnostic for patterns in function pointer types)
 - rust-lang/rust#157928 (Eagerly fetch typeck results when linting)
 - rust-lang/rust#159672 (Improve suggestions when multiples tuples implement the same trait)
 - rust-lang/rust#159861 (Add documentation for the `non_exhaustive` attribute)
 - rust-lang/rust#159907 (Fix `hidden_glob_reexports` in `rustc_ast`)
 - rust-lang/rust#159998 (Align expect messages with guidance)
 - rust-lang/rust#160145 (Expand checks for register_tool)
 - rust-lang/rust#160307 (Update `minifier` version to `0.4.0`)
@RalfJung
RalfJung deleted the const-atomic branch August 2, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants