You can see in the source code, there are some public re-imports like Future, FutureExt, Stream, StreamExt, Sink, SinkExt, etc. You can not find them in the documentation, but you can use them anyway.
The documented way to use these re-imports are:
futures::future::Future
futures::future::FutureExt
futures::stream::Stream
futures::stream::StreamExt
futures::sink::Sink
futures::sink::SinkExt
But you can just use:
futures::Future
futures::FutureExt
futures::Stream
futures::StreamExt
futures::Sink
futures::SinkExt
And actually, the auto import feature of Rust Analyzer prefers the undocumented import paths.
I think if an item is not documented, then you shall not use it. Of course this can be fixed on Rust Analyzer’s side by filtering undocumented items, but why are these re-imports there anyway? Is this some kind of pattern or something?
Typically you'll do this when an internal tool (typically a macro) relies on the item having a well-known, publicly accessible path (i.e. so it can be accessed from a downstream crate), but you don't actually want it to be part of your public API.
That I can understand, but these items are already accessible on the documented paths. Any macros related to these item can use the documented ones instead. There is no need for these hidden ones being public.
Taking a look at the Git blame, these re-exports (note: this is the standard terminology for pub use, not "re-imports") were made doc(hidden) as part of https://github.com/rust-lang/futures-rs/pull/1069. The discussion about this change is in this thread—it looks like the original plan was to remove the re-exports entirely to clean up the generated rustdocs for the crate root, and simply making them doc(hidden) was a compromise to maintain the ease of use futures::{Future, FutureExt} and such (and to avoid breaking existing code, as @alice speculated).