Repository: rust-lang/futures-rs
Pull request #2875 (2024-08-02 18:54:43)

Add accessors for the inner of stream::Iter
This PR adds analogues to the methods of all the stream/sink combinators which allow accessing the thing being wrapped. Here it lets you access the iterator, which is currently not possible.

I'm intentionally not using the `delegate_access_inner` macro, because the doc comments describe the inner member as being a stream or sink, which it is not for `Iter` (it also requires using `pin_project`, which `Iter` does not do or need).


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 13e2ebcc..3314bc3a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,6 +24,7 @@ missing_debug_implementations = "warn"
 rust_2018_idioms = "warn"
 single_use_lifetimes = "warn"
 unreachable_pub = "warn"
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(futures_sanitizer)'] }
 # unsafe_op_in_unsafe_fn = "warn" # Set at crate-level instead since https://github.com/rust-lang/rust/pull/100081 is not available on MSRV
 [workspace.lints.clippy]
 incompatible_msrv = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/12273, https://github.com/rust-lang/rust-clippy/issues/12257
diff --git a/futures-core/src/stream.rs b/futures-core/src/stream.rs
index ad5350b7..19114e7d 100644
--- a/futures-core/src/stream.rs
+++ b/futures-core/src/stream.rs
@@ -38,15 +38,15 @@ pub trait Stream {
     /// stream state:
     ///
     /// - `Poll::Pending` means that this stream's next value is not ready
-    /// yet. Implementations will ensure that the current task will be notified
-    /// when the next value may be ready.
+    ///   yet. Implementations will ensure that the current task will be notified
+    ///   when the next value may be ready.
     ///
     /// - `Poll::Ready(Some(val))` means that the stream has successfully
-    /// produced a value, `val`, and may produce further values on subsequent
-    /// `poll_next` calls.
+    ///   produced a value, `val`, and may produce further values on subsequent
+    ///   `poll_next` calls.
     ///
     /// - `Poll::Ready(None)` means that the stream has terminated, and
-    /// `poll_next` should not be invoked again.
+    ///   `poll_next` should not be invoked again.
     ///
     /// # Panics
     ///
diff --git a/futures-executor/src/lib.rs b/futures-executor/src/lib.rs
index ec3a5a40..a0dc49d7 100644
--- a/futures-executor/src/lib.rs
+++ b/futures-executor/src/lib.rs
@@ -46,7 +46,6 @@
 ))]
 #![warn(missing_docs, unsafe_op_in_unsafe_fn)]
 #![cfg_attr(docsrs, feature(doc_cfg))]
-#![allow(clippy::thread_local_initializer_can_be_made_const)] // clippy bug: this lint doesn't consider MSRV
 
 #[cfg(feature = "std")]
 extern crate std;
diff --git a/futures-macro/src/join.rs b/futures-macro/src/join.rs
index 94e356f7..0e891b3a 100644
--- a/futures-macro/src/join.rs
+++ b/futures-macro/src/join.rs
@@ -1,4 +1,4 @@
-//! The futures-rs `join! macro implementation.
+//! The futures-rs `join!` macro implementation.
 
 use proc_macro::TokenStream;
 use proc_macro2::{Span, TokenStream as TokenStream2};
diff --git a/futures-macro/src/select.rs b/futures-macro/src/select.rs
index 57bb74a8..7b45cfe4 100644
--- a/futures-macro/src/select.rs
+++ b/futures-macro/src/select.rs
@@ -1,4 +1,4 @@
-//! The futures-rs `select! macro implementation.
+//! The futures-rs `select!` macro implementation.
 
 use proc_macro::TokenStream;
 use proc_macro2::Span;
diff --git a/futures-util/src/abortable.rs b/futures-util/src/abortable.rs
index 9dbcfc2b..e1e79e37 100644
--- a/futures-util/src/abortable.rs
+++ b/futures-util/src/abortable.rs
@@ -64,7 +64,7 @@ impl<T> Abortable<T> {
     /// This means that it will return `true` even if:
     /// * `abort` was called after the task had completed.
     /// * `abort` was called while the task was being polled - the task may still be running and
-    /// will not be stopped until `poll` returns.
+    ///   will not be stopped until `poll` returns.
     pub fn is_aborted(&self) -> bool {
         self.inner.aborted.load(Ordering::Relaxed)
     }
@@ -200,7 +200,7 @@ impl AbortHandle {
     /// even if:
     /// * `abort` was called after the task had completed.
     /// * `abort` was called while the task was being polled - the task may still be running and
-    /// will not be stopped until `poll` returns.
+    ///   will not be stopped until `poll` returns.
     ///
     /// This operation has a Relaxed ordering.
     pub fn is_aborted(&self) -> bool {
diff --git a/futures-util/src/async_await/select_mod.rs b/futures-util/src/async_await/select_mod.rs
index 84c6ca5a..638a92eb 100644
--- a/futures-util/src/async_await/select_mod.rs
+++ b/futures-util/src/async_await/select_mod.rs
@@ -3,6 +3,7 @@
 macro_rules! document_select_macro {
     // This branch is required for `futures 0.3.1`, from before select_biased was introduced
     ($select:item) => {
+        #[allow(clippy::too_long_first_doc_paragraph)]
         /// Polls multiple futures and streams simultaneously, executing the branch
         /// for the future that finishes first. If multiple futures are ready,
         /// one will be pseudo-randomly selected at runtime. Futures directly
@@ -153,6 +154,7 @@ macro_rules! document_select_macro {
     ($select:item $select_biased:item) => {
         document_select_macro!($select);
 
+        #[allow(clippy::too_long_first_doc_paragraph)]
         /// Polls multiple futures and streams simultaneously, executing the branch
         /// for the future that finishes first. Unlike [`select!`], if multiple futures are ready,
         /// one will be selected in order of declaration. Futures directly
diff --git a/futures-util/src/async_await/stream_select_mod.rs b/futures-util/src/async_await/stream_select_mod.rs
index 541b4cd9..039e65a6 100644
--- a/futures-util/src/async_await/stream_select_mod.rs
+++ b/futures-util/src/async_await/stream_select_mod.rs
@@ -3,6 +3,7 @@
 #[doc(hidden)]
 pub use futures_macro::stream_select_internal;
 
+#[allow(clippy::too_long_first_doc_paragraph)]
 /// Combines several streams, all producing the same `Item` type, into one stream.
 /// This is similar to `select_all` but does not require the streams to all be the same type.
 /// It also keeps the streams inline, and does not require `Box<dyn Stream>`s to be allocated.
diff --git a/futures-util/src/compat/compat03as01.rs b/futures-util/src/compat/compat03as01.rs
index 2f9d65e7..3c5bb77b 100644
--- a/futures-util/src/compat/compat03as01.rs
+++ b/futures-util/src/compat/compat03as01.rs
@@ -15,6 +15,7 @@ use futures_sink::Sink as Sink03;
 use std::marker::PhantomData;
 use std::{mem, pin::Pin, sync::Arc, task::Context};
 
+#[allow(clippy::too_long_first_doc_paragraph)] // clippy bug, see https://github.com/rust-lang/rust-clippy/issues/13315
 /// Converts a futures 0.3 [`TryFuture`](futures_core::future::TryFuture) or
 /// [`TryStream`](futures_core::stream::TryStream) into a futures 0.1
 /// [`Future`](futures_01::future::Future) or
diff --git a/futures-util/src/lib.rs b/futures-util/src/lib.rs
index abe35e68..c5af6960 100644
--- a/futures-util/src/lib.rs
+++ b/futures-util/src/lib.rs
@@ -10,7 +10,6 @@
     )
 ))]
 #![warn(missing_docs, unsafe_op_in_unsafe_fn)]
-#![cfg_attr(feature = "write-all-vectored", feature(io_slice_advance))]
 #![cfg_attr(docsrs, feature(doc_cfg))]
 #![allow(clippy::needless_borrow)] // https://github.com/rust-lang/futures-rs/pull/2558#issuecomment-1030745203
 #![allow(clippy::arc_with_non_send_sync)] // false positive https://github.com/rust-lang/rust-clippy/issues/11076
diff --git a/futures-util/src/stream/iter.rs b/futures-util/src/stream/iter.rs
index 20471c2e..48b6519a 100644
--- a/futures-util/src/stream/iter.rs
+++ b/futures-util/src/stream/iter.rs
@@ -10,6 +10,23 @@ pub struct Iter<I> {
     iter: I,
 }
 
+impl<I> Iter<I> {
+    /// Acquires a reference to the underlying iterator that this stream is pulling from.
+    pub fn get_ref(&self) -> &I {
+        &self.iter
+    }
+
+    /// Acquires a mutable reference to the underlying iterator that this stream is pulling from.
+    pub fn get_mut(&mut self) -> &mut I {
+        &mut self.iter
+    }
+
+    /// Consumes this stream, returning the underlying iterator.
+    pub fn into_inner(self) -> I {
+        self.iter
+    }
+}
+
 impl<I> Unpin for Iter<I> {}
 
 /// Converts an `Iterator` into a `Stream` which is always ready
diff --git a/futures-util/src/stream/select_with_strategy.rs b/futures-util/src/stream/select_with_strategy.rs
index 3be933e9..4375f3e2 100644
--- a/futures-util/src/stream/select_with_strategy.rs
+++ b/futures-util/src/stream/select_with_strategy.rs
@@ -75,6 +75,7 @@ pin_project! {
     }
 }
 
+#[allow(clippy::too_long_first_doc_paragraph)]
 /// This function will attempt to pull items from both streams. You provide a
 /// closure to tell [`SelectWithStrategy`] which stream to poll. The closure can
 /// store state on `SelectWithStrategy` to which it will receive a `&mut` on every
diff --git a/futures-util/src/stream/stream/flatten_unordered.rs b/futures-util/src/stream/stream/flatten_unordered.rs
index 37811a10..c79edbd2 100644
--- a/futures-util/src/stream/stream/flatten_unordered.rs
+++ b/futures-util/src/stream/stream/flatten_unordered.rs
@@ -119,7 +119,7 @@ impl SharedPollState {
     /// - `!WAKING` as
     ///   * Wakers called during the `POLLING` phase won't propagate their calls
     ///   * `POLLING` phase can't start if some of the wakers are active
-    ///   So no wrapped waker can touch the inner waker's cell, it's safe to poll again.
+    ///     So no wrapped waker can touch the inner waker's cell, it's safe to poll again.
     fn stop_polling(&self, to_poll: u8, will_be_woken: bool) -> u8 {
         self.state
             .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut value| {


Test patch:
diff --git a/futures/tests/no-std/build.rs b/futures/tests/no-std/build.rs
index a96a6827..ba79f203 100644
--- a/futures/tests/no-std/build.rs
+++ b/futures/tests/no-std/build.rs
@@ -1,6 +1,7 @@
 use std::{env, process::Command};
 
 fn main() {
+    println!("cargo:rustc-check-cfg=cfg(nightly)");
     if is_nightly() {
         println!("cargo:rustc-cfg=nightly");
     }