Skip to content

proof of concept: replace select! with join_me_maybe::join!#1

Draft
oconnor663 wants to merge 3 commits into
masterfrom
join_me_maybe
Draft

proof of concept: replace select! with join_me_maybe::join!#1
oconnor663 wants to merge 3 commits into
masterfrom
join_me_maybe

Conversation

@oconnor663

@oconnor663 oconnor663 commented Jan 28, 2026

Copy link
Copy Markdown
Owner

This PR (internal to my clone, not upstream) is a proof of concept that join_me_maybe::join can replace select! loops in nontrivial cases. There are some scattered changes that go against the grain of surrounding code, and it would need a fair bit of cleanup if it was going to be seriously reviewed, but the goal here is just showing (myself) that it's possible to get it compiling and passing tests. This required adding several features to join_me_maybe along the way, and it was a useful forcing function.

My motivation was this post by @nikomatsakis: https://smallcultfollowing.com/babysteps/blog/2022/06/13/async-cancellation-a-case-study-of-pub-sub-in-mini-redis. The thesis is that select! is error-prone, and it would be nice to replace it in common use cases, but it also has some superpowers that make it hard to replace. select! arms get lowered to a match in the calling function, which means they can mutate the same variables, and they can also short-circuit with return or ?. Since an arm body doesn't run until select! has dropped all the "scrutinee" futures, borrows in the bodies don't conflict with those futures either. At the same time, for better or worse, it's also possible to .await async function calls in the bodies. join_me_maybe approaches this with several similar features:

  • Arm bodies get lowered to a match, as in select!. That means that only one body can run at a time. However, to avoid deadlocks, the bodies (whichever one is running at any given time) are still concurrent with all the "scrutinee" futures. (It's a join! rather than a select!, so by default we wait for all of them.)
  • Stream support. We can execute a body expression for each element that comes out of a stream.
  • Return support. Error handling with ? works. This requires some aggressive macro shenanigans, because each body can also evaluate to a value "the normal way" (though we don't use that in this case).
  • Interior mutability of "labeled" streams (and technically futures too). See this section of the join_me_maybe docs. This is the most complicated bit, and the most likely to change in future versions of join_me_maybe. For each labeled future or stream, there's a "canceller" in scope, and it supports a with_mut method that exposes the labeled future/stream for mutation. That's what lets us add work to the StreamMap over time. Though see the TODO above that join arm.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec5716f9f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cmd/subscribe.rs
Comment thread src/cmd/subscribe.rs
@oconnor663 oconnor663 marked this pull request as draft February 21, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant