Skip to content

Commit 50532d8

Browse files
committed
Make from_ptr const fn on Rust 1.83+
1 parent 710d179 commit 50532d8

File tree

3 files changed

+161
-65
lines changed

3 files changed

+161
-65
lines changed

src/lib.rs

Lines changed: 154 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -586,37 +586,42 @@ impl AtomicBool {
586586
}
587587

588588
// TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
589-
/// Creates a new `AtomicBool` from a pointer.
590-
///
591-
/// # Safety
592-
///
593-
/// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can
594-
/// be bigger than `align_of::<bool>()`).
595-
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
596-
/// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
597-
/// behind `ptr` must have a happens-before relationship with atomic accesses via the returned
598-
/// value (or vice-versa).
599-
/// * In other words, time periods where the value is accessed atomically may not overlap
600-
/// with periods where the value is accessed non-atomically.
601-
/// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the
602-
/// duration of lifetime `'a`. Most use cases should be able to follow this guideline.
603-
/// * This requirement is also trivially satisfied if all accesses (atomic or not) are done
604-
/// from the same thread.
605-
/// * If this atomic type is *not* lock-free:
606-
/// * Any accesses to the value behind `ptr` must have a happens-before relationship
607-
/// with accesses via the returned value (or vice-versa).
608-
/// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
609-
/// be compatible with operations performed by this atomic type.
610-
/// * This method must not be used to create overlapping or mixed-size atomic accesses, as
611-
/// these are not supported by the memory model.
612-
///
613-
/// [valid]: core::ptr#safety
614-
#[inline]
615-
#[must_use]
616-
pub unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a Self {
617-
#[allow(clippy::cast_ptr_alignment)]
618-
// SAFETY: guaranteed by the caller
619-
unsafe { &*(ptr as *mut Self) }
589+
const_fn! {
590+
const_if: #[cfg(not(portable_atomic_no_const_mut_refs))];
591+
/// Creates a new `AtomicBool` from a pointer.
592+
///
593+
/// This is `const fn` on Rust 1.83+.
594+
///
595+
/// # Safety
596+
///
597+
/// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can
598+
/// be bigger than `align_of::<bool>()`).
599+
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
600+
/// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
601+
/// behind `ptr` must have a happens-before relationship with atomic accesses via the returned
602+
/// value (or vice-versa).
603+
/// * In other words, time periods where the value is accessed atomically may not overlap
604+
/// with periods where the value is accessed non-atomically.
605+
/// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the
606+
/// duration of lifetime `'a`. Most use cases should be able to follow this guideline.
607+
/// * This requirement is also trivially satisfied if all accesses (atomic or not) are done
608+
/// from the same thread.
609+
/// * If this atomic type is *not* lock-free:
610+
/// * Any accesses to the value behind `ptr` must have a happens-before relationship
611+
/// with accesses via the returned value (or vice-versa).
612+
/// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
613+
/// be compatible with operations performed by this atomic type.
614+
/// * This method must not be used to create overlapping or mixed-size atomic accesses, as
615+
/// these are not supported by the memory model.
616+
///
617+
/// [valid]: core::ptr#safety
618+
#[inline]
619+
#[must_use]
620+
pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a Self {
621+
#[allow(clippy::cast_ptr_alignment)]
622+
// SAFETY: guaranteed by the caller
623+
unsafe { &*(ptr as *mut Self) }
624+
}
620625
}
621626

622627
/// Returns `true` if operations on values of this type are lock-free.
@@ -1598,37 +1603,42 @@ impl<T> AtomicPtr<T> {
15981603
}
15991604

16001605
// TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
1601-
/// Creates a new `AtomicPtr` from a pointer.
1602-
///
1603-
/// # Safety
1604-
///
1605-
/// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1606-
/// can be bigger than `align_of::<*mut T>()`).
1607-
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
1608-
/// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
1609-
/// behind `ptr` must have a happens-before relationship with atomic accesses via the returned
1610-
/// value (or vice-versa).
1611-
/// * In other words, time periods where the value is accessed atomically may not overlap
1612-
/// with periods where the value is accessed non-atomically.
1613-
/// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the
1614-
/// duration of lifetime `'a`. Most use cases should be able to follow this guideline.
1615-
/// * This requirement is also trivially satisfied if all accesses (atomic or not) are done
1616-
/// from the same thread.
1617-
/// * If this atomic type is *not* lock-free:
1618-
/// * Any accesses to the value behind `ptr` must have a happens-before relationship
1619-
/// with accesses via the returned value (or vice-versa).
1620-
/// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
1621-
/// be compatible with operations performed by this atomic type.
1622-
/// * This method must not be used to create overlapping or mixed-size atomic accesses, as
1623-
/// these are not supported by the memory model.
1624-
///
1625-
/// [valid]: core::ptr#safety
1626-
#[inline]
1627-
#[must_use]
1628-
pub unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a Self {
1629-
#[allow(clippy::cast_ptr_alignment)]
1630-
// SAFETY: guaranteed by the caller
1631-
unsafe { &*(ptr as *mut Self) }
1606+
const_fn! {
1607+
const_if: #[cfg(not(portable_atomic_no_const_mut_refs))];
1608+
/// Creates a new `AtomicPtr` from a pointer.
1609+
///
1610+
/// This is `const fn` on Rust 1.83+.
1611+
///
1612+
/// # Safety
1613+
///
1614+
/// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1615+
/// can be bigger than `align_of::<*mut T>()`).
1616+
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
1617+
/// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
1618+
/// behind `ptr` must have a happens-before relationship with atomic accesses via the returned
1619+
/// value (or vice-versa).
1620+
/// * In other words, time periods where the value is accessed atomically may not overlap
1621+
/// with periods where the value is accessed non-atomically.
1622+
/// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the
1623+
/// duration of lifetime `'a`. Most use cases should be able to follow this guideline.
1624+
/// * This requirement is also trivially satisfied if all accesses (atomic or not) are done
1625+
/// from the same thread.
1626+
/// * If this atomic type is *not* lock-free:
1627+
/// * Any accesses to the value behind `ptr` must have a happens-before relationship
1628+
/// with accesses via the returned value (or vice-versa).
1629+
/// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
1630+
/// be compatible with operations performed by this atomic type.
1631+
/// * This method must not be used to create overlapping or mixed-size atomic accesses, as
1632+
/// these are not supported by the memory model.
1633+
///
1634+
/// [valid]: core::ptr#safety
1635+
#[inline]
1636+
#[must_use]
1637+
pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a Self {
1638+
#[allow(clippy::cast_ptr_alignment)]
1639+
// SAFETY: guaranteed by the caller
1640+
unsafe { &*(ptr as *mut Self) }
1641+
}
16321642
}
16331643

16341644
/// Returns `true` if operations on values of this type are lock-free.
@@ -2721,9 +2731,50 @@ let atomic_forty_two = ", stringify!($atomic_type), "::new(42);
27212731
}
27222732

27232733
// TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
2734+
#[cfg(not(portable_atomic_no_const_mut_refs))]
2735+
doc_comment! {
2736+
concat!("Creates a new reference to an atomic integer from a pointer.
2737+
2738+
This is `const fn` on Rust 1.83+.
2739+
2740+
# Safety
2741+
2742+
* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
2743+
can be bigger than `align_of::<", stringify!($int_type), ">()`).
2744+
* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
2745+
* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
2746+
behind `ptr` must have a happens-before relationship with atomic accesses via
2747+
the returned value (or vice-versa).
2748+
* In other words, time periods where the value is accessed atomically may not
2749+
overlap with periods where the value is accessed non-atomically.
2750+
* This requirement is trivially satisfied if `ptr` is never used non-atomically
2751+
for the duration of lifetime `'a`. Most use cases should be able to follow
2752+
this guideline.
2753+
* This requirement is also trivially satisfied if all accesses (atomic or not) are
2754+
done from the same thread.
2755+
* If this atomic type is *not* lock-free:
2756+
* Any accesses to the value behind `ptr` must have a happens-before relationship
2757+
with accesses via the returned value (or vice-versa).
2758+
* Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
2759+
be compatible with operations performed by this atomic type.
2760+
* This method must not be used to create overlapping or mixed-size atomic
2761+
accesses, as these are not supported by the memory model.
2762+
2763+
[valid]: core::ptr#safety"),
2764+
#[inline]
2765+
#[must_use]
2766+
pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self {
2767+
#[allow(clippy::cast_ptr_alignment)]
2768+
// SAFETY: guaranteed by the caller
2769+
unsafe { &*(ptr as *mut Self) }
2770+
}
2771+
}
2772+
#[cfg(portable_atomic_no_const_mut_refs)]
27242773
doc_comment! {
27252774
concat!("Creates a new reference to an atomic integer from a pointer.
27262775
2776+
This is `const fn` on Rust 1.83+.
2777+
27272778
# Safety
27282779
27292780
* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
@@ -4107,9 +4158,50 @@ This type has the same in-memory representation as the underlying floating point
41074158
}
41084159

41094160
// TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
4161+
#[cfg(not(portable_atomic_no_const_mut_refs))]
41104162
doc_comment! {
41114163
concat!("Creates a new reference to an atomic float from a pointer.
41124164
4165+
This is `const fn` on Rust 1.83+.
4166+
4167+
# Safety
4168+
4169+
* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
4170+
can be bigger than `align_of::<", stringify!($float_type), ">()`).
4171+
* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
4172+
* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
4173+
behind `ptr` must have a happens-before relationship with atomic accesses via
4174+
the returned value (or vice-versa).
4175+
* In other words, time periods where the value is accessed atomically may not
4176+
overlap with periods where the value is accessed non-atomically.
4177+
* This requirement is trivially satisfied if `ptr` is never used non-atomically
4178+
for the duration of lifetime `'a`. Most use cases should be able to follow
4179+
this guideline.
4180+
* This requirement is also trivially satisfied if all accesses (atomic or not) are
4181+
done from the same thread.
4182+
* If this atomic type is *not* lock-free:
4183+
* Any accesses to the value behind `ptr` must have a happens-before relationship
4184+
with accesses via the returned value (or vice-versa).
4185+
* Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
4186+
be compatible with operations performed by this atomic type.
4187+
* This method must not be used to create overlapping or mixed-size atomic
4188+
accesses, as these are not supported by the memory model.
4189+
4190+
[valid]: core::ptr#safety"),
4191+
#[inline]
4192+
#[must_use]
4193+
pub const unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self {
4194+
#[allow(clippy::cast_ptr_alignment)]
4195+
// SAFETY: guaranteed by the caller
4196+
unsafe { &*(ptr as *mut Self) }
4197+
}
4198+
}
4199+
#[cfg(portable_atomic_no_const_mut_refs)]
4200+
doc_comment! {
4201+
concat!("Creates a new reference to an atomic float from a pointer.
4202+
4203+
This is `const fn` on Rust 1.83+.
4204+
41134205
# Safety
41144206
41154207
* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this

src/tests/helper.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,7 @@ macro_rules! __test_atomic_int_pub {
14591459
#[cfg(not(portable_atomic_no_const_mut_refs))]
14601460
const GET_MUT: $atomic_type = {
14611461
let mut a = <$atomic_type>::new(10);
1462+
let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) };
14621463
*a.get_mut() = 5;
14631464
a
14641465
};
@@ -1547,6 +1548,7 @@ macro_rules! __test_atomic_float_pub {
15471548
#[cfg(not(portable_atomic_no_const_mut_refs))]
15481549
const GET_MUT: $atomic_type = {
15491550
let mut a = <$atomic_type>::new(10.);
1551+
let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) };
15501552
*a.get_mut() = 5.;
15511553
a
15521554
};
@@ -1650,6 +1652,7 @@ macro_rules! __test_atomic_bool_pub {
16501652
#[cfg(not(portable_atomic_no_const_mut_refs))]
16511653
const GET_MUT: $atomic_type = {
16521654
let mut a = <$atomic_type>::new(true);
1655+
let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) };
16531656
*a.get_mut() = false;
16541657
a
16551658
};
@@ -1710,6 +1713,7 @@ macro_rules! __test_atomic_ptr_pub {
17101713
#[cfg(not(portable_atomic_no_const_mut_refs))]
17111714
const GET_MUT: $atomic_type = {
17121715
let mut a = <$atomic_type>::new(ptr::null_mut());
1716+
let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) };
17131717
*a.get_mut() = ptr::null_mut::<u8>().wrapping_add(1);
17141718
a
17151719
};

src/utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ macro_rules! const_fn {
120120
(
121121
const_if: #[cfg($($cfg:tt)+)];
122122
$(#[$($attr:tt)*])*
123-
$vis:vis const fn $($rest:tt)*
123+
$vis:vis const $($rest:tt)*
124124
) => {
125125
#[cfg($($cfg)+)]
126126
$(#[$($attr)*])*
127-
$vis const fn $($rest)*
127+
$vis const $($rest)*
128128
#[cfg(not($($cfg)+))]
129129
$(#[$($attr)*])*
130-
$vis fn $($rest)*
130+
$vis $($rest)*
131131
};
132132
}
133133

0 commit comments

Comments
 (0)