diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fd7b437c6..95fef3bbfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,59 +127,41 @@ jobs: - run: cargo update -Z minimal-versions - run: cargo build --workspace --all-features - thumbv6m: - name: cargo build --target thumbv6m-none-eabi + no-std: + name: cargo build --target ${{ matrix.target }} + strategy: + matrix: + target: + - thumbv6m-none-eabi + - thumbv7m-none-eabi runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install Rust run: rustup update nightly && rustup default nightly - - run: rustup target add thumbv6m-none-eabi + - run: rustup target add ${{ matrix.target }} - run: cargo install cargo-hack # remove dev-dependencies to avoid https://github.com/rust-lang/cargo/issues/4866 - run: cargo hack --remove-dev-deps --workspace - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv6m-none-eabi \ - --no-default-features \ - --features unstable,cfg-target-has-atomic - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv6m-none-eabi \ - --no-default-features \ - --features alloc,unstable,cfg-target-has-atomic - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv6m-none-eabi \ - --no-default-features \ - --features async-await,unstable,cfg-target-has-atomic - - thumbv7m: - name: cargo build --target thumbv7m-none-eabi - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install Rust - run: rustup update nightly && rustup default nightly - - run: rustup target add thumbv7m-none-eabi - - run: cargo install cargo-hack - # remove dev-dependencies to avoid https://github.com/rust-lang/cargo/issues/4866 - - run: cargo hack --remove-dev-deps --workspace + cargo hack build --manifest-path futures/tests/no-std/Cargo.toml \ + --each-feature --optional-deps \ + --target ${{ matrix.target }} - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv7m-none-eabi \ + cargo hack build --workspace --ignore-private \ + --exclude futures-test --exclude futures-macro \ --no-default-features \ - --features unstable,cfg-target-has-atomic + --target ${{ matrix.target }} - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv7m-none-eabi \ - --no-default-features \ - --features alloc + cargo hack build --workspace --ignore-private \ + --exclude futures-test --exclude futures-macro \ + --no-default-features --features alloc --ignore-unknown-features \ + --target ${{ matrix.target }} - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv7m-none-eabi \ - --no-default-features \ - --features async-await + cargo hack build --workspace --ignore-private \ + --exclude futures-test --exclude futures-macro \ + --no-default-features --features async-await,alloc --ignore-unknown-features \ + --target ${{ matrix.target }} bench: name: cargo bench @@ -212,6 +194,19 @@ jobs: --workspace --exclude futures-test \ --features unstable --ignore-unknown-features + # When this job failed, run ci/no_atomic_cas.sh and commit result changes. + # TODO(taiki-e): Ideally, this should be automated using a bot that creates + # PR when failed, but there is no bandwidth to implement it + # right now... + codegen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update nightly && rustup default nightly + - run: ci/no_atomic_cas.sh + - run: git diff --exit-code + san: name: cargo test -Z sanitizer=${{ matrix.sanitizer }} strategy: diff --git a/Cargo.toml b/Cargo.toml index f972a73d2c..d27a9f2885 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ members = [ "futures/tests/macro-tests", "futures/tests/macro-reexport", + "futures/tests/no-std", "examples/functional", "examples/imperative", diff --git a/ci/no_atomic_cas.sh b/ci/no_atomic_cas.sh new file mode 100755 index 0000000000..24faa70487 --- /dev/null +++ b/ci/no_atomic_cas.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -euo pipefail +IFS=$'\n\t' + +cd "$(cd "$(dirname "$0")" && pwd)"/.. + +file="no_atomic_cas.rs" + +{ + echo "// This file is @generated by $(basename "$0")." + echo "// It is not intended for manual editing." + echo "" + echo "const NO_ATOMIC_CAS_TARGETS: &[&str] = &[" +} >"$file" + +for target in $(rustc --print target-list); do + res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \ + | jq -r "select(.\"atomic-cas\" == false)") + [[ -z "$res" ]] || echo " \"$target\"," >>"$file" +done + +echo "];" >>"$file" diff --git a/futures-channel/Cargo.toml b/futures-channel/Cargo.toml index 82a2a7e5fa..344c3a7854 100644 --- a/futures-channel/Cargo.toml +++ b/futures-channel/Cargo.toml @@ -17,11 +17,10 @@ std = ["alloc", "futures-core/std"] alloc = ["futures-core/alloc"] sink = ["futures-sink"] -# Unstable features -# These features are outside of the normal semver guarantees and require the -# `unstable` feature as an explicit opt-in to unstable API. -unstable = ["futures-core/unstable"] -cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic"] +# These features are no longer used. +# TODO: remove in the next major version. +unstable = [] +cfg-target-has-atomic = [] [dependencies] futures-core = { path = "../futures-core", version = "=1.0.0-alpha.0", default-features = false } diff --git a/futures-channel/build.rs b/futures-channel/build.rs new file mode 100644 index 0000000000..c4f341d480 --- /dev/null +++ b/futures-channel/build.rs @@ -0,0 +1,42 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] + +use std::env; + +include!("no_atomic_cas.rs"); + +// The rustc-cfg listed below are considered public API, but it is *unstable* +// and outside of the normal semver guarantees: +// +// - `futures_no_atomic_cas` +// Assume the target does not have atomic CAS (compare-and-swap). +// This is usually detected automatically by the build script, but you may +// need to enable it manually when building for custom targets or using +// non-cargo build systems that don't run the build script. +// +// With the exceptions mentioned above, the rustc-cfg strings below are +// *not* public API. Please let us know by opening a GitHub issue if your build +// environment requires some way to enable these cfgs other than by executing +// our build script. +fn main() { + let target = match env::var("TARGET") { + Ok(target) => target, + Err(e) => { + println!( + "cargo:warning={}: unable to get TARGET environment variable: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + // Note that this is `no_*`, not `has_*`. This allows treating + // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't + // run. This is needed for compatibility with non-cargo build systems that + // don't run the build script. + if NO_ATOMIC_CAS_TARGETS.contains(&&*target) { + println!("cargo:rustc-cfg=futures_no_atomic_cas"); + } + + println!("cargo:rerun-if-changed=no_atomic_cas.rs"); +} diff --git a/futures-channel/no_atomic_cas.rs b/futures-channel/no_atomic_cas.rs new file mode 120000 index 0000000000..3d7380fadd --- /dev/null +++ b/futures-channel/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/futures-channel/src/lib.rs b/futures-channel/src/lib.rs index 41a4a19af7..9377a3e2c2 100644 --- a/futures-channel/src/lib.rs +++ b/futures-channel/src/lib.rs @@ -11,7 +11,6 @@ //! All items are only available when the `std` or `alloc` feature of this //! library is activated, and it is activated by default. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] // It cannot be included in the published code because this lints have false positives in the minimum required version. @@ -19,12 +18,9 @@ #![warn(clippy::all)] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] $item )*}; } diff --git a/futures-core/Cargo.toml b/futures-core/Cargo.toml index 7ab0879209..5824655350 100644 --- a/futures-core/Cargo.toml +++ b/futures-core/Cargo.toml @@ -16,9 +16,8 @@ default = ["std"] std = ["alloc"] alloc = [] -# Unstable features -# These features are outside of the normal semver guarantees and require the -# `unstable` feature as an explicit opt-in to unstable API. +# These features are no longer used. +# TODO: remove in the next major version. unstable = [] cfg-target-has-atomic = [] diff --git a/futures-core/build.rs b/futures-core/build.rs new file mode 100644 index 0000000000..c4f341d480 --- /dev/null +++ b/futures-core/build.rs @@ -0,0 +1,42 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] + +use std::env; + +include!("no_atomic_cas.rs"); + +// The rustc-cfg listed below are considered public API, but it is *unstable* +// and outside of the normal semver guarantees: +// +// - `futures_no_atomic_cas` +// Assume the target does not have atomic CAS (compare-and-swap). +// This is usually detected automatically by the build script, but you may +// need to enable it manually when building for custom targets or using +// non-cargo build systems that don't run the build script. +// +// With the exceptions mentioned above, the rustc-cfg strings below are +// *not* public API. Please let us know by opening a GitHub issue if your build +// environment requires some way to enable these cfgs other than by executing +// our build script. +fn main() { + let target = match env::var("TARGET") { + Ok(target) => target, + Err(e) => { + println!( + "cargo:warning={}: unable to get TARGET environment variable: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + // Note that this is `no_*`, not `has_*`. This allows treating + // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't + // run. This is needed for compatibility with non-cargo build systems that + // don't run the build script. + if NO_ATOMIC_CAS_TARGETS.contains(&&*target) { + println!("cargo:rustc-cfg=futures_no_atomic_cas"); + } + + println!("cargo:rerun-if-changed=no_atomic_cas.rs"); +} diff --git a/futures-core/no_atomic_cas.rs b/futures-core/no_atomic_cas.rs new file mode 120000 index 0000000000..3d7380fadd --- /dev/null +++ b/futures-core/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/futures-core/src/lib.rs b/futures-core/src/lib.rs index f3bd9ab928..e363ff777d 100644 --- a/futures-core/src/lib.rs +++ b/futures-core/src/lib.rs @@ -1,6 +1,5 @@ //! Core traits and types for asynchronous operations in Rust. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] // It cannot be included in the published code because this lints have false positives in the minimum required version. @@ -8,9 +7,6 @@ #![warn(clippy::all)] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(feature = "alloc")] extern crate alloc; diff --git a/futures-core/src/task/__internal/mod.rs b/futures-core/src/task/__internal/mod.rs index 77e3678075..c902eb4bfb 100644 --- a/futures-core/src/task/__internal/mod.rs +++ b/futures-core/src/task/__internal/mod.rs @@ -1,4 +1,4 @@ -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(not(futures_no_atomic_cas))] mod atomic_waker; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(not(futures_no_atomic_cas))] pub use self::atomic_waker::AtomicWaker; diff --git a/futures-macro/build.rs b/futures-macro/build.rs index fec7b029eb..ff8630ce69 100644 --- a/futures-macro/build.rs +++ b/futures-macro/build.rs @@ -23,4 +23,6 @@ fn main() { if cfg.probe_rustc_version(1, 45) { println!("cargo:rustc-cfg=fn_like_proc_macro"); } + + println!("cargo:rerun-if-changed=build.rs"); } diff --git a/futures-task/Cargo.toml b/futures-task/Cargo.toml index e64f4c5362..9590d4a54c 100644 --- a/futures-task/Cargo.toml +++ b/futures-task/Cargo.toml @@ -16,9 +16,8 @@ default = ["std"] std = ["alloc"] alloc = [] -# Unstable features -# These features are outside of the normal semver guarantees and require the -# `unstable` feature as an explicit opt-in to unstable API. +# These features are no longer used. +# TODO: remove in the next major version. unstable = [] cfg-target-has-atomic = [] diff --git a/futures-task/build.rs b/futures-task/build.rs new file mode 100644 index 0000000000..c4f341d480 --- /dev/null +++ b/futures-task/build.rs @@ -0,0 +1,42 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] + +use std::env; + +include!("no_atomic_cas.rs"); + +// The rustc-cfg listed below are considered public API, but it is *unstable* +// and outside of the normal semver guarantees: +// +// - `futures_no_atomic_cas` +// Assume the target does not have atomic CAS (compare-and-swap). +// This is usually detected automatically by the build script, but you may +// need to enable it manually when building for custom targets or using +// non-cargo build systems that don't run the build script. +// +// With the exceptions mentioned above, the rustc-cfg strings below are +// *not* public API. Please let us know by opening a GitHub issue if your build +// environment requires some way to enable these cfgs other than by executing +// our build script. +fn main() { + let target = match env::var("TARGET") { + Ok(target) => target, + Err(e) => { + println!( + "cargo:warning={}: unable to get TARGET environment variable: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + // Note that this is `no_*`, not `has_*`. This allows treating + // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't + // run. This is needed for compatibility with non-cargo build systems that + // don't run the build script. + if NO_ATOMIC_CAS_TARGETS.contains(&&*target) { + println!("cargo:rustc-cfg=futures_no_atomic_cas"); + } + + println!("cargo:rerun-if-changed=no_atomic_cas.rs"); +} diff --git a/futures-task/no_atomic_cas.rs b/futures-task/no_atomic_cas.rs new file mode 120000 index 0000000000..3d7380fadd --- /dev/null +++ b/futures-task/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/futures-task/src/lib.rs b/futures-task/src/lib.rs index 6693c53af0..439af135af 100644 --- a/futures-task/src/lib.rs +++ b/futures-task/src/lib.rs @@ -1,6 +1,5 @@ //! Tools for working with tasks. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] // It cannot be included in the published code because this lints have false positives in the minimum required version. @@ -8,15 +7,12 @@ #![warn(clippy::all)] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(feature = "alloc")] extern crate alloc; macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] $item )*}; } diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml index f2b3dc9d33..0829c936eb 100644 --- a/futures-util/Cargo.toml +++ b/futures-util/Cargo.toml @@ -27,11 +27,14 @@ channel = ["std", "futures-channel"] # These features are outside of the normal semver guarantees and require the # `unstable` feature as an explicit opt-in to unstable API. unstable = ["futures-core/unstable", "futures-task/unstable"] -cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic", "futures-task/cfg-target-has-atomic"] bilock = [] read-initializer = ["io", "futures-io/read-initializer", "futures-io/unstable"] write-all-vectored = ["io"] +# These features are no longer used. +# TODO: remove in the next major version. +cfg-target-has-atomic = [] + [build-dependencies] autocfg = "1" diff --git a/futures-util/build.rs b/futures-util/build.rs index fec7b029eb..ffe9711414 100644 --- a/futures-util/build.rs +++ b/futures-util/build.rs @@ -1,11 +1,44 @@ #![warn(rust_2018_idioms, single_use_lifetimes)] use autocfg::AutoCfg; +use std::env; -// The rustc-cfg strings below are *not* public API. Please let us know by -// opening a GitHub issue if your build environment requires some way to enable -// these cfgs other than by executing our build script. +include!("no_atomic_cas.rs"); + +// The rustc-cfg listed below are considered public API, but it is *unstable* +// and outside of the normal semver guarantees: +// +// - `futures_no_atomic_cas` +// Assume the target does not have atomic CAS (compare-and-swap). +// This is usually detected automatically by the build script, but you may +// need to enable it manually when building for custom targets or using +// non-cargo build systems that don't run the build script. +// +// With the exceptions mentioned above, the rustc-cfg strings below are +// *not* public API. Please let us know by opening a GitHub issue if your build +// environment requires some way to enable these cfgs other than by executing +// our build script. fn main() { + let target = match env::var("TARGET") { + Ok(target) => target, + Err(e) => { + println!( + "cargo:warning={}: unable to get TARGET environment variable: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + // Note that this is `no_*`, not `has_*`. This allows treating + // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't + // run. This is needed for compatibility with non-cargo build systems that + // don't run the build script. + if NO_ATOMIC_CAS_TARGETS.contains(&&*target) { + println!("cargo:rustc-cfg=futures_no_atomic_cas"); + } + let cfg = match AutoCfg::new() { Ok(cfg) => cfg, Err(e) => { @@ -23,4 +56,6 @@ fn main() { if cfg.probe_rustc_version(1, 45) { println!("cargo:rustc-cfg=fn_like_proc_macro"); } + + println!("cargo:rerun-if-changed=no_atomic_cas.rs"); } diff --git a/futures-util/no_atomic_cas.rs b/futures-util/no_atomic_cas.rs new file mode 120000 index 0000000000..3d7380fadd --- /dev/null +++ b/futures-util/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/futures-util/src/lib.rs b/futures-util/src/lib.rs index 6329bc2f42..2bdca31a81 100644 --- a/futures-util/src/lib.rs +++ b/futures-util/src/lib.rs @@ -1,7 +1,6 @@ //! Combinators and utilities for working with `Future`s, `Stream`s, `Sink`s, //! and the `AsyncRead` and `AsyncWrite` traits. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(feature = "read-initializer", feature(read_initializer))] #![cfg_attr(feature = "write-all-vectored", feature(io_slice_advance))] #![cfg_attr(not(feature = "std"), no_std)] @@ -12,9 +11,6 @@ #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] #![cfg_attr(docsrs, feature(doc_cfg))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(all(feature = "bilock", not(feature = "unstable")))] compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features"); @@ -53,7 +49,7 @@ pub mod __private { macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] $item )*}; } diff --git a/futures-util/src/stream/mod.rs b/futures-util/src/stream/mod.rs index 69249f430e..8814056556 100644 --- a/futures-util/src/stream/mod.rs +++ b/futures-util/src/stream/mod.rs @@ -37,11 +37,11 @@ pub use self::stream::ReadyChunks; #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] pub use self::stream::Forward; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] pub use self::stream::{BufferUnordered, Buffered, ForEachConcurrent, TryForEachConcurrent}; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] #[cfg(feature = "alloc")] @@ -59,7 +59,7 @@ pub use self::try_stream::{ #[cfg(feature = "std")] pub use self::try_stream::IntoAsyncRead; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] pub use self::try_stream::{TryBufferUnordered, TryBuffered}; diff --git a/futures-util/src/stream/stream/mod.rs b/futures-util/src/stream/stream/mod.rs index bfd5e94f97..4636e6a3ab 100644 --- a/futures-util/src/stream/stream/mod.rs +++ b/futures-util/src/stream/stream/mod.rs @@ -933,7 +933,7 @@ pub trait StreamExt: Stream { /// fut.await; /// # }) /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn for_each_concurrent( self, @@ -1066,7 +1066,7 @@ pub trait StreamExt: Stream { /// assert_eq!(Err(oneshot::Canceled), fut.await); /// # }) /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn try_for_each_concurrent( self, @@ -1293,7 +1293,7 @@ pub trait StreamExt: Stream { /// # Panics /// /// This method will panic if `n` is zero. - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn buffered(self, n: usize) -> Buffered where @@ -1342,7 +1342,7 @@ pub trait StreamExt: Stream { /// assert_eq!(buffered.next().await, None); /// # Ok::<(), i32>(()) }).unwrap(); /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn buffer_unordered(self, n: usize) -> BufferUnordered where @@ -1510,7 +1510,7 @@ pub trait StreamExt: Stream { /// library is activated, and it is activated by default. #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn split(self) -> (SplitSink, SplitStream) where diff --git a/futures-util/src/stream/try_stream/mod.rs b/futures-util/src/stream/try_stream/mod.rs index 299a019cdb..22fd74453c 100644 --- a/futures-util/src/stream/try_stream/mod.rs +++ b/futures-util/src/stream/try_stream/mod.rs @@ -684,7 +684,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); /// # Ok::<(), Box>(()) }).unwrap(); /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered where @@ -760,7 +760,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); /// # Ok::<(), Box>(()) }).unwrap(); /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] fn try_buffered(self, n: usize) -> TryBuffered where diff --git a/futures/Cargo.toml b/futures/Cargo.toml index bfdfefce29..ccad92db45 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -47,11 +47,14 @@ thread-pool = ["executor", "futures-executor/thread-pool"] # These features are outside of the normal semver guarantees and require the # `unstable` feature as an explicit opt-in to unstable API. unstable = ["futures-core/unstable", "futures-task/unstable", "futures-channel/unstable", "futures-io/unstable", "futures-util/unstable"] -cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic", "futures-task/cfg-target-has-atomic", "futures-channel/cfg-target-has-atomic", "futures-util/cfg-target-has-atomic"] bilock = ["futures-util/bilock"] read-initializer = ["futures-io/read-initializer", "futures-util/read-initializer"] write-all-vectored = ["futures-util/write-all-vectored"] +# These features are no longer used. +# TODO: remove in the next major version. +cfg-target-has-atomic = [] + [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/futures/src/lib.rs b/futures/src/lib.rs index e0867994f2..bc51ac7c7b 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -78,7 +78,6 @@ //! The majority of examples and code snippets in this crate assume that they are //! inside an async block as written above. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(feature = "read-initializer", feature(read_initializer))] #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -88,9 +87,6 @@ #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] #![cfg_attr(docsrs, feature(doc_cfg))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(all(feature = "bilock", not(feature = "unstable")))] compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features"); diff --git a/futures/tests/no-std/Cargo.toml b/futures/tests/no-std/Cargo.toml new file mode 100644 index 0000000000..9526732e34 --- /dev/null +++ b/futures/tests/no-std/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "no-std" +version = "0.1.0" +authors = ["Taiki Endo "] +edition = "2018" +publish = false + +[features] +futures-core-alloc = ["futures-core/alloc"] +futures-task-alloc = ["futures-task/alloc"] +futures-channel-alloc = ["futures-channel/alloc"] +futures-util-alloc = ["futures-util/alloc"] +futures-util-async-await = ["futures-util/async-await"] +futures-alloc = ["futures/alloc"] +futures-async-await = ["futures/async-await"] + +[dependencies] +futures-core = { path = "../../../futures-core", optional = true, default-features = false } +futures-task = { path = "../../../futures-task", optional = true, default-features = false } +futures-channel = { path = "../../../futures-channel", optional = true, default-features = false } +futures-util = { path = "../../../futures-util", optional = true, default-features = false } +futures = { path = "../..", optional = true, default-features = false } diff --git a/futures/tests/no-std/build.rs b/futures/tests/no-std/build.rs new file mode 100644 index 0000000000..a96a68274b --- /dev/null +++ b/futures/tests/no-std/build.rs @@ -0,0 +1,14 @@ +use std::{env, process::Command}; + +fn main() { + if is_nightly() { + println!("cargo:rustc-cfg=nightly"); + } +} + +fn is_nightly() -> bool { + env::var_os("RUSTC") + .and_then(|rustc| Command::new(rustc).arg("--version").output().ok()) + .and_then(|output| String::from_utf8(output.stdout).ok()) + .map_or(false, |version| version.contains("nightly") || version.contains("dev")) +} diff --git a/futures/tests/no-std/src/lib.rs b/futures/tests/no-std/src/lib.rs new file mode 100644 index 0000000000..308218d6b7 --- /dev/null +++ b/futures/tests/no-std/src/lib.rs @@ -0,0 +1,31 @@ +#![cfg(nightly)] +#![no_std] +#![feature(cfg_target_has_atomic)] + +#[cfg(feature = "futures-core-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_core::task::__internal::AtomicWaker as _; + +#[cfg(feature = "futures-task-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_task::ArcWake as _; + +#[cfg(feature = "futures-channel-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_channel::oneshot as _; + +#[cfg(any(feature = "futures", feature = "futures-alloc"))] +#[cfg(target_has_atomic = "ptr")] +pub use futures::task::AtomicWaker as _; + +#[cfg(feature = "futures-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures::stream::FuturesOrdered as _; + +#[cfg(any(feature = "futures-util", feature = "futures-util-alloc"))] +#[cfg(target_has_atomic = "ptr")] +pub use futures_util::task::AtomicWaker as _; + +#[cfg(feature = "futures-util-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_util::stream::FuturesOrdered as _; diff --git a/no_atomic_cas.rs b/no_atomic_cas.rs new file mode 100644 index 0000000000..0819af1a45 --- /dev/null +++ b/no_atomic_cas.rs @@ -0,0 +1,11 @@ +// This file is @generated by no_atomic_cas.sh. +// It is not intended for manual editing. + +const NO_ATOMIC_CAS_TARGETS: &[&str] = &[ + "avr-unknown-gnu-atmega328", + "msp430-none-elf", + "riscv32i-unknown-none-elf", + "riscv32imc-unknown-none-elf", + "thumbv4t-none-eabi", + "thumbv6m-none-eabi", +];