Skip to content

Commit

Permalink
portable-atomic-util: portable_atomic_unstable_coerce_unsized cfg option
Browse files Browse the repository at this point in the history
with minor CI updates
  • Loading branch information
brodycj committed Nov 20, 2024
1 parent 391606a commit daefbb8
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 10 deletions.
1 change: 1 addition & 0 deletions .github/.cspell/project-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ uart
umax
umin
unclonable
unsize
usart
uscat
uwrite
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ jobs:
if: matrix.rust == 'nightly-2024-02-13'

- run: tools/test.sh -vv ${TARGET:-} ${DOCTEST_XCOMPILE:-} ${BUILD_STD:-} ${RELEASE:-}
- run: tools/test.sh -vv ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_unstable_coerce_unsized
if: startsWith(matrix.rust, 'nightly')
# We test doctest only once with the default build conditions because doctest is slow. Both api-test
# and src/tests have extended copies of doctest, so this will not reduce test coverage.
# portable_atomic_no_outline_atomics only affects x86_64, AArch64, Arm, powerpc64, and RISC-V Linux.
Expand All @@ -367,8 +371,9 @@ jobs:
# __kuser_helper_version < 5, etc., and is not a public API.
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_test_outline_atomics_detect_false
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_test_outline_atomics_detect_false
# powerpc64 is skipped because tested below.
if: (matrix.target == '' && !contains(matrix.rust, 'i686') || startsWith(matrix.target, 'x86_64')) || startsWith(matrix.target, 'aarch64') && !(contains(matrix.target, '-musl') && matrix.flags == '') || startsWith(matrix.target, 'armv5te') || matrix.target == 'arm-linux-androideabi'
# PowerPC 64-bit is skipped because it is tested below.
# arm-linux-androideabi is removed due to an apparent issue between Rust nightly & QEmu in CI testing
if: (matrix.target == '' && !contains(matrix.rust, 'i686') || startsWith(matrix.target, 'x86_64')) || startsWith(matrix.target, 'aarch64') && !(contains(matrix.target, '-musl') && matrix.flags == '') || startsWith(matrix.target, 'armv5te')
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
QEMU_CPU: power7 # no quadword-atomics
Expand Down
22 changes: 22 additions & 0 deletions portable-atomic-util/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ See [#1] for other primitives being considered for addition to this crate.
[portable-atomic]: https://github.com/taiki-e/portable-atomic
[#1]: https://github.com/taiki-e/portable-atomic/issues/1

## Optional cfg

One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags):

```toml
# .cargo/config.toml
[target.<target>]
rustflags = ["--cfg", "portable_atomic_unstable_coerce_unsized"]
```

Or set environment variable:

```sh
RUSTFLAGS="--cfg portable_atomic_unstable_coerce_unsized" cargo ...
```

- <a name="portable-atomic-unstable-coerce-unsized"></a>**`--cfg portable_atomic_unstable_coerce_unsized`**<br> support standard coercing of `Arc<T>` to `Arc<U>` and same for weak references

This coercing requires Rust nightly to compile (with help from [unstable `CoerceUnsized` trait](https://doc.rust-lang.org/nightly/core/ops/trait.CoerceUnsized.html)).

See [this issue comment](https://github.com/taiki-e/portable-atomic/issues/143#issuecomment-1866488569) for another known workaround.

<!-- tidy:crate-doc:end -->

## License
Expand Down
2 changes: 1 addition & 1 deletion portable-atomic-util/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn main() {
// Custom cfgs set by build script. Not public API.
// grep -F 'cargo:rustc-cfg=' build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
println!(
"cargo:rustc-check-cfg=cfg(portable_atomic_no_alloc,portable_atomic_no_alloc_layout_extras,portable_atomic_no_core_unwind_safe,portable_atomic_no_error_in_core,portable_atomic_no_futures_api,portable_atomic_no_io_safety,portable_atomic_no_io_vec,portable_atomic_no_maybe_uninit,portable_atomic_no_min_const_generics,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_sanitize_thread)"
"cargo:rustc-check-cfg=cfg(portable_atomic_no_alloc,portable_atomic_no_alloc_layout_extras,portable_atomic_no_core_unwind_safe,portable_atomic_no_error_in_core,portable_atomic_no_futures_api,portable_atomic_no_io_safety,portable_atomic_no_io_vec,portable_atomic_no_maybe_uninit,portable_atomic_no_min_const_generics,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_sanitize_thread,portable_atomic_unstable_coerce_unsized)"
);
}

Expand Down
25 changes: 18 additions & 7 deletions portable-atomic-util/src/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ use core::{
ptr::{self, NonNull},
usize,
};
#[cfg(portable_atomic_unstable_coerce_unsized)]
use core::{marker::Unsize, ops::CoerceUnsized};

/// A soft limit on the amount of references that may be made to an `Arc`.
///
Expand Down Expand Up @@ -77,11 +79,13 @@ macro_rules! acquire {
/// This is an equivalent to [`std::sync::Arc`], but using [portable-atomic] for synchronization.
/// See the documentation for [`std::sync::Arc`] for more details.
///
/// **Note:** Unlike `std::sync::Arc`, coercing `Arc<T>` to `Arc<U>` is not supported at all.
/// **Note:** Unlike `std::sync::Arc`, coercing `Arc<T>` to `Arc<U>` is only possible if
/// the optional cfg `portable_atomic_unstable_coerce_unsized` is enabled, as documented for this crate,
/// and this optional cfg item is only supported with Rust nightly version.
/// This is because coercing the pointee requires the
/// [unstable `CoerceUnsized` trait](https://doc.rust-lang.org/nightly/core/ops/trait.CoerceUnsized.html).
/// See [this issue comment](https://github.com/taiki-e/portable-atomic/issues/143#issuecomment-1866488569)
/// for the known workaround.
/// for a workaround that works with stable and beta Rust channels.
///
/// [portable-atomic]: https://crates.io/crates/portable-atomic
///
Expand Down Expand Up @@ -115,6 +119,9 @@ impl<T: ?Sized + core::panic::RefUnwindSafe> core::panic::UnwindSafe for Arc<T>
#[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))]
impl<T: ?Sized + std::panic::RefUnwindSafe> std::panic::UnwindSafe for Arc<T> {}

#[cfg(portable_atomic_unstable_coerce_unsized)]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}

impl<T: ?Sized> Arc<T> {
#[inline]
fn into_inner_non_null(this: Self) -> NonNull<ArcInner<T>> {
Expand Down Expand Up @@ -174,6 +181,9 @@ pub struct Weak<T: ?Sized> {
unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}

#[cfg(portable_atomic_unstable_coerce_unsized)]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}

impl<T: ?Sized> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("(Weak)")
Expand Down Expand Up @@ -1508,11 +1518,11 @@ impl Arc<dyn Any + Send + Sync> {
/// }
///
/// let my_string = "Hello World".to_string();
// TODO: CoerceUnsized is needed to cast Arc<String> -> Arc<dyn Any + Send + Sync> directly.
// /// print_if_string(Arc::new(my_string));
// /// print_if_string(Arc::new(0i8));
/// print_if_string(Arc::from(Box::new(my_string) as Box<dyn Any + Send + Sync>));
/// print_if_string(Arc::from(Box::new(0i8) as Box<dyn Any + Send + Sync>));
/// // or with "--cfg portable_atomic_unstable_coerce_unsized" in RUSTFLAGS (requires Rust nightly):
/// // print_if_string(Arc::new(my_string));
/// // print_if_string(Arc::new(0i8));
/// ```
#[inline]
pub fn downcast<T>(self) -> Result<Arc<T>, Self>
Expand Down Expand Up @@ -2234,7 +2244,7 @@ impl<T> Default for Arc<[T]> {
#[inline]
fn default() -> Self {
// TODO: we cannot use non-allocation optimization (https://github.com/rust-lang/rust/blob/1.80.0/library/alloc/src/sync.rs#L3449)
// for now due to casting Arc<[T; N]> -> Arc<[T]> requires unstable CoerceUnsized.
// for now since casting Arc<[T; N]> -> Arc<[T]> requires unstable CoerceUnsized from Rust nightly.
let arr: [T; 0] = [];
Arc::from(arr)
}
Expand Down Expand Up @@ -2292,7 +2302,8 @@ impl<T, const N: usize> From<[T; N]> for Arc<[T]> {
/// ```
#[inline]
fn from(v: [T; N]) -> Self {
// Casting Arc<[T; N]> -> Arc<[T]> requires unstable CoerceUnsized, so we convert via Box.
// Casting Arc<[T; N]> -> Arc<[T]> requires unstable CoerceUnsized (with Rust nightly),
// so we convert via Box to support stable & beta Rust channels.
// Since the compiler knows the actual size and metadata, the intermediate allocation is
// optimized and generates the same code as when using CoerceUnsized and convert Arc<[T; N]> to Arc<[T]>.
// https://github.com/taiki-e/portable-atomic/issues/143#issuecomment-1866488569
Expand Down
24 changes: 24 additions & 0 deletions portable-atomic-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ See [#1] for other primitives being considered for addition to this crate.
[portable-atomic]: https://github.com/taiki-e/portable-atomic
[#1]: https://github.com/taiki-e/portable-atomic/issues/1
## Optional cfg
One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags):
```toml
# .cargo/config.toml
[target.<target>]
rustflags = ["--cfg", "portable_atomic_unstable_coerce_unsized"]
```
Or set environment variable:
```sh
RUSTFLAGS="--cfg portable_atomic_unstable_coerce_unsized" cargo ...
```
- <a name="portable-atomic-unstable-coerce-unsized"></a>**`--cfg portable_atomic_unstable_coerce_unsized`**<br> support standard coercing of `Arc<T>` to `Arc<U>` and same for weak references
This coercing requires Rust nightly to compile (with help from [unstable `CoerceUnsized` trait](https://doc.rust-lang.org/nightly/core/ops/trait.CoerceUnsized.html)).
See [this issue comment](https://github.com/taiki-e/portable-atomic/issues/143#issuecomment-1866488569) for another known workaround.
<!-- tidy:crate-doc:end -->
*/

Expand Down Expand Up @@ -60,6 +82,8 @@ See [#1] for other primitives being considered for addition to this crate.
#![allow(clippy::inline_always)]
// docs.rs only (cfg is enabled by docs.rs, not build script)
#![cfg_attr(docsrs, feature(doc_cfg))]
// Enable custom unsized coercions if needed by cfg
#![cfg_attr(portable_atomic_unstable_coerce_unsized, feature(coerce_unsized, unsize))]

#[cfg(all(feature = "alloc", not(portable_atomic_no_alloc)))]
extern crate alloc;
Expand Down

0 comments on commit daefbb8

Please sign in to comment.