Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making the Stream adaptor structures public in tokio-stream #6658

Merged
merged 12 commits into from
Jul 2, 2024
Merged

Making the Stream adaptor structures public in tokio-stream #6658

merged 12 commits into from
Jul 2, 2024

Conversation

sharpened-nacho
Copy link
Contributor

@sharpened-nacho sharpened-nacho commented Jun 25, 2024

Motivation

The StreamExt trait provides the helpful method take, map, and the like on Streams. But the structures themselves (Take, Map, etc.) are not visible outside the crate, as they are not pub use in stream_ext.rs.

Solution

Re-exported publicly all the structures in stream_ext.rs except for Collect, which is different and should not be exported as stated in its documentation. Re-exported them publicly again in lib.rs.

Added a function in a test with return type Chain to show that it can be part of an external function signature.

Closes: #6656

@Darksonn Darksonn added the A-tokio-stream Area: The tokio-stream crate label Jun 25, 2024
Comment on lines 84 to 87
pub use stream_ext::{
AllFuture, AnyFuture, Chain, Filter, FilterMap, FoldFuture, Fuse, Map, MapWhile, Merge, Next,
Peekable, Skip, SkipWhile, Take, TakeWhile, Then, TryNext,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put them in a sub-module so they don't clutter the front page of the crate documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could define a pub mod adapters in lib.rs that pub uses all the structures like so

/// Some doc
pub mod adapters {
    pub use crate::stream_ext::{
        AllFuture, AnyFuture, Chain, Filter, FilterMap, FoldFuture, Fuse, Map, MapWhile, Merge,
        Next, Peekable, Skip, SkipWhile, Take, TakeWhile, Then, TryNext,
    };
}

This seemed very hacky to me, so I thought : should all the mods for those structures really be in the stream_ext folder/mod? The exposed structure of the crate is very different from its folder structure. How about having adapters.rs next to stream_ext.rs, and an adapters folder with all the mods' files? That would mimic the std::iter structure.
That way we could also put the "sources" (std::iter terminology) related mods (empty, iter, once, etc.) in their folder - but expose them the same as they are right now to not break anything.

I would have 2 questions with this though :

  • is that considered a breaking change (the interface is kept the same)? And even if not, do you want to do this sort of big changes?
  • what to do with the all-alone collect mod? Keeping it in stream_ext? Lift it next to stream_ext and adapters?

But perhaps I'm going too far, I have no idea 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining an inline module like you suggested in the beginning is fine. (But the other approaches would not be considered breaking.)

@sharpened-nacho
Copy link
Contributor Author

My bad again, sorry for pushing bad commits like those, I'm not familiar enough with large projects to understand how to run all tests.
I hope you can squash all that mess together...

@sharpened-nacho
Copy link
Contributor Author

I just realized the equivalence between tokio_stream::StreamExt and futures_util::StreamExt. But in futures-util the structures are exported and accessible, so the functionality I needed is ultimately not needed here, I can get it from futures-util.
Do you want to roll back to the beginning and drop this PR?

Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't worry about pushing bad commits. We always squash together PRs on merge, so it's really not a problem.

tokio-stream/src/lib.rs Outdated Show resolved Hide resolved
Next, Peekable, Skip, SkipWhile, Take, TakeWhile, Then, TryNext,
};
}

cfg_time! {
pub use stream_ext::timeout::{Elapsed, Timeout};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I just saw that PR #4601 exposed Timeout directly in tokio_stream. What to do about this ?

Expose them all in adapters, but also keep this one exposed flush in tokio_stream to not break anything?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can make the top-level ones #[doc(hidden)].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and added the error struct Elapsed in the new imports, so that's it's still somewhere to be found if a user who used it wants to update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the tests don't like the addition of #[doc(hidden)]...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@obi1kenobi is there any way to tell cargo-semver-checks to treat a #[doc(hidden)] item as part of the public API? Context is that we want to change the path of an exported item.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it seems that we can't deplicate re-export yet :(

rust-lang/rust#30827

Copy link
Contributor

@obi1kenobi obi1kenobi Jul 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking the re-export as deprecated doesn't have any effect in rustc / clippy / generated rustdoc HTML (it is simply ignored) but does have the desirable effect in cargo-semver-checks.

Unless I've missed something, to me that still sounds fine to use. After all, it didn't seem like originally (before I suggested it) you were planning to deprecate the re-export, so you weren't going to get any rustc / clippy / HTML docs notices on it anyway.

I don't think anything bad happens here when rustc / clippy / generated docs start fully supporting deprecations on re-exports.

What does it do for a re-export to be considered deprecated as you say?

Deprecations and doc(hidden)-ness are properties of import paths like tokio_stream::stream_ext::timeout::Timeout, not the items behind those names. The full details are in this post, but as a summary:

#[doc(hidden)]
pub mod example {
    pub struct Something;
}

pub use example::Something;

In this example, this_crate::Something is public API because in writing that path, we didn't touch any hidden items along the way. this_crate::example::Something is hidden and non-public API because the this_crate::example prefix is hidden. Conceptually, you can imagine walking the components ["this_crate", "example", "Something"] and checking whether each of them is hidden or deprecated — if so, the entire path is hidden / deprecated as well.

Broadly speaking, the rustc / clippy / rustdoc HTML implementations only consider deprecations as properties of items like pub struct Something, not of import paths. (There are some subtleties — check out the linked post for more details.) cargo-semver-checks used to do the same thing — it's much simpler and it isn't a priori obvious that deprecation is a path property. This led to tons of false-positives so I spent a couple of months to fix it, as the post describes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the in-depth message. Now I have the full picture, and - as you say on your blog - the semantics are perfectly aligned with what we want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! As always, please feel free to ping me if you have further questions or run into any issues 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @obi1kenobi. I agree that using #[deprecated] is reasonable in this case.

Comment on lines 86 to 89
pub use crate::stream_ext::{
AllFuture, AnyFuture, Chain, Filter, FilterMap, FoldFuture, Fuse, Map, MapWhile, Merge,
Next, Peekable, Skip, SkipWhile, Take, TakeWhile, Then, TryNext,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, can we drop Next from the list? I'd like to only export the ones that implement Stream, not the ones that implement Future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there are a few more futures. Can you remove those too? You can view the generated docs with your change here.

Also, we should probably move Elapsed to the root. It's an error type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preview is very cool!
Done!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed Elapsed from the doc(hidden) and deprecated combo as well, since it is the only way to access it.

Added pub to all use declarations in stream_ext.rs, except for Collect
as it should stay private, as stated in its doc.

Exported the structures in lib.rs directly at the root of the library.

Fixes: #6656
Added an indirection function that has tokio_stream::Chain in
its interface to see that the Chain type can be imported and used.

Ref: #6656
Reformatted the previous commit.

Ref: #6656
Created an inline adapters mod that contains the adapter types, to
keep the tokio_stream interface organized.

Fixes: #6656
Removed redundant target in label.

Fixes: #6656
Added an export for the three last stream structures in the
adapters mod.
Timeout was already exposed in tokio_stream directly due to
#4601 ; left it there.

Fixes: #6656
Excluded the Timeout and its error struct exposed flush
in tokio_stream. Added that exposed struct in the new
adapters mod, so that it's still somewhere.

Ref: #6656
My previous phrasing was catastrophic.

Ref: #6656
Deprecated the import on top of having it doc hidden.

Ref: #6656
Removed Next as it's a Future, not a Stream, from the interface.

Ref: #6656
Removed the various structures implementing Future and not Stream.

Ref: #6656
Moved the Elapsed error to the root, un-deprecating it.

Ref: #6656
Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

@Darksonn Darksonn enabled auto-merge (squash) July 2, 2024 20:47
@Darksonn Darksonn merged commit c8f3539 into tokio-rs:master Jul 2, 2024
77 checks passed
@devanoneth
Copy link

Any idea when a new version of tokio-stream will be rolled with this in it? Thanks!

@Darksonn
Copy link
Contributor

I don't have concrete plans for a release right now.

@djc
Copy link
Contributor

djc commented Sep 5, 2024

Releasing in #6825.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio-stream Area: The tokio-stream crate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Making the Stream adaptor structures public in tokio-stream
6 participants