Repository navigation
feat(kio)!: generate async wrappers behind an async feature - #7506
Conversation
Quest-Claim: bdbdb42af8e85df3
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
…oice Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
The maintainer picked the method attribute from the generator spike. `#[kio::wrapper]` on a `poll_*` method adds the `async fn` that awaits it, deriving its name, signature, generics, and docs. Its contract is covered by kio-macros' behavior and UI tests. kio's async methods move behind a new default-off `async` feature, so a poll-only kio compiles no coroutines. moq-net's `async` enables it, and moq-net's broadcast wrappers become generated. `just rs coroutines` scans the MIR of kio's and moq-net's poll-only builds in the nightly feature matrix. The spike fixtures are removed: the runner appended its own `wrapper` to kio-macros, and its results stay linked from the quest by commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 10 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 398809e
No actionable bugs found. Reusing kio-macros keeps ordinary poll methods canonical without introducing a second declaration language. The generated wrappers preserve the converted methods' polling behavior; feature forwarding and the explicit migration note match the default-off kio API change. Keeping the nontrivial helpers handwritten is appropriate, and the isolated coroutine scan complements the wrapper tests.
Verification: static inspection of the generator, conversions, feature wiring, tests and scan script only. I did not run builds/tests, reproduce the compile-time measurements, or independently verify the reported feature matrix.
(Written by OpenAI)
There was a problem hiding this comment.
Important
moq-auth's library build breaks with this change: it calls kio::Shared::wait, now gated behind kio/async, but never enables that feature. The workspace build hides this through feature unification, so it slips past just ci and just rs features.
Reviewed changes
#[kio::wrapper]macro — kio-macros derives anasync fnbeside apoll_*method, copying the poll's visibility, generics (turbofish'd), docs,cfg, and deprecation, plus a back-link, and errors with a compile error beside the original method when the shape is rejected. Covered by behavior tests andtrybuildUI diagnostics.- kio
asyncfeature — a new default-off feature (impliesmacros) gates every kioasyncmethod;simnow enablesasync;extern crate self as kiowidens toany(test, feature = "async");MIGRATE.md,Cargo.toml, doctests, and module docs updated. - moq-net wrappers —
Requests::{requested_track, closed},Consumer::closed, andDemand::wanted_changedare now generated from their polls, andmoq-net'sasyncenableskio/async. just rs coroutines—sh/rs/coroutines.shscans a crate's MIR and fails on any coroutine not on its shrinking allowlist; kio allows none, moq-net allowsuntil/run_front/serve_front. Wired intojust rs features.- Feature wiring and docs —
moq-shapergainskio/async;rs/AGENTS.md, the async-feature quest, andrs/kio/MIGRATE.mddescribe the generated-and-gated rule.
⚠️ moq-auth's library build no longer compiles without kio/async
Gating Shared::wait behind kio/async leaves moq-auth without the feature it needs, and moq-auth depends on kio directly rather than through moq-net, so nothing pulls the feature in. With resolver 2, a non-test build resolves kio from normal dependencies only (cargo tree -e features,no-dev -p moq-auth shows default + serde, no async), so a plain cargo check -p moq-auth and any downstream consumer of the published crate fail. The workspace gate and the PR's --all-targets check both unify kio/async in (the sim dev-dependency enables it), which is why CI stays green.
Technical details
# moq-auth needs the kio `async` feature
## Affected sites
- `rs/moq-auth/Cargo.toml:25` — `kio = { workspace = true, features = ["serde"] }` enables no `async`.
- `rs/moq-auth/src/lease.rs:416` — `Shared::wait` in `Lease::reported`.
- `rs/moq-auth/src/client.rs:215` — `Shared::wait` on `connection.lifecycle` (`kio::Shared<Lifecycle>`).
- `rs/moq-auth/src/client.rs:528` — `Shared::wait` on the `Log`'s `kio::Shared<Vec<Request>>`.
## Required outcome
- `cargo check -p moq-auth` (library, default features and `--no-default-features`) compiles.
## Suggested approach
- Add `"async"` to `moq-auth`'s `kio` features, as `moq-shaper` did, until it grows its own `async` feature per the quest.
- Add an isolated lib-only check for the kio-direct crates, since both the workspace gate and `--all-targets` unify `kio/async` through the `sim` dev-dependency and mask the gap.
## Open questions for the human
- Should `just rs coroutines` list `moq-auth` with `--allow` now, or wait for its `async` feature?deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
`poll_self`, `poll__`, and `poll_1` reached `Ident::new_raw`, which panics for the keywords that cannot be raw and for a digit-led name. Report a spanned error on the poll instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moq-auth depends on kio directly and awaits `Shared::wait`, now behind `kio/async`. The workspace build unified the feature in through the `kio/sim` dev-dependencies, so only a lone library build broke. `just rs features` now checks that build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 1f79714
No new actionable bugs found since my previous review. The explicit moq-auth kio/async dependency fixes the isolated-library build issue identified in Pullfrog's review, and the lib-only feature check targets the feature-unification blind spot. The wrapper now reports a spanned error for unnameable identifiers instead of panicking, addressing the existing finding.
These are focused fixes that preserve the generator's direction without extra abstraction. Base-branch changes were separated from this update. Verification was static inspection only; I did not run the build matrix or UI tests.
(Written by OpenAI)
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Re-reviewed the commits since the prior Pullfrog review on 398809e, which had raised two issues. Both are fixed correctly, and the new code introduces nothing else.
moq-authlibrary build —rs/moq-auth/Cargo.tomlenableskio/asyncon itskiodependency, soShared::waitresolves in an isolated library build, andjust rs featuresadds a lone--lib --all-featuresmoq-authcheck to guard the feature-unification blind spot.- Unnameable wrapper names —
#[kio::wrapper]emits a spanned error for a name that is no identifier even raw (poll_self,poll__,poll_1) instead of panicking inIdent::new_raw; the guard set (_,self,Self,super,crate) matches proc-macro2's raw-identifier restrictions exactly, andtests/ui/wrapper_unnameablecovers all three cases.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
Resolve the clock re-export conflict: keep main's random exports and the async-gated drive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Problem
The async-feature quest needed a generator before rollout. This PR first held the spike that compared three generators (results). The maintainer has now chosen one, so the PR builds it and makes the first conversions.
Decisions
The maintainer chose this on 2026-11-01:
Choices I made while implementing it, listed here for review:
#[cfg_attr(feature = "async", kio::wrapper)], so the macro emits nocfgitself. A poll-only build then never runs the proc macro, the macro doesn't depend on what a caller names its feature, and the attribute is testable inside kio-macros. The spike had the macro also emit#[cfg(feature = "async")], which would have checked kio-macros' own features in its tests. The CI scan below catches any wrapper left ungated.Awaits [poll_x](Self::poll_x).is added. The poll keeps its own docs, so they now say what the call resolves to rather than how it registers a waiter. I rewrote kio's andbroadcast's poll docs to read that way. The link only goes from the wrapper to the poll, because a link back would break whenasyncis off.&selfor&mut self. There is exactly one&Waiterargument, in any position. Every other argument has a plain name and is passed to every poll unchanged, so it must beCopyor a reference; rustc points at the argument otherwise. The return type isPoll<T>. The wrapper copies the poll's visibility, generics (named in a turbofish),doc,cfg, anddeprecated. A poll named after a keyword (poll_match) gets a raw identifier. I checked this against every direct wrapper in kio and moq-net: they include waiter-last polls,&mutarguments, polls generic only in the return type, and methodwhereclauses.#[kio::machine], which a test covers.asynchelpers that do more than await one poll stay hand-written and gated:Queue::push, thewaitpredicates,clock::drive, andInterval::tick.simenablesasync, because the simulator only runs async tests.wrapperto kio-macros, which now conflicts, and the results stay linked by commit.Approach
#[kio::wrapper]lives in kio-macros (rs/kio/macros/src/wrapper.rs), and kio re-exports it undermacros.asyncfeature (impliesmacros). Without it, kio compiles no coroutines:Consumer/Producer/ConsumerWeak/ProducerWeak::closed,Producer::wanted_changed, andQueue::popare generated, and the rest are gated.asyncnow enableskio/async. moq-net'sbroadcastwrappers are generated:Requests::{requested_track, closed},Consumer::closed, andDemand::wanted_changed.sh/rs/coroutines.shemits a library's MIR and fails on anyasyncfn body, block, or closure not on its allowlist. It also fails when an allowed name disappears, so the list can only shrink.just rs coroutinesruns it on kio's and moq-net's poll-only builds, andjust rs features(nightly and release PRs) runs that, following the rule that isolated feature builds stay out of the gate. moq-net's poll-only build still compiles three:auth::until, and origin'srun_frontandserve_front.kio/asyncthrough moq-net, so each enables it. I checked every direct kio dependent's normal-dependency graph withcargo tree -e features,normal, then built each crate that lacked it as a lone library.just rs featuresnow checks moq-auth's lone library build, because the workspace'skio/simdev-dependencies unifykio/asyncback in and hid the break (Pullfrog's finding).poll_self,poll__,poll_1), gets a spanned error instead of a proc-macro panic (Pullfrog's finding), with a UI case.rs/AGENTS.md's rule now says the async helper is generated and gated.asyncdefault off.Impact
features = ["async"].rs/kio/MIGRATE.mdhas the migration note. Version bumps stay manual.wrapperattribute (additive).Checks
cargo clippy -D warningson kio, for each ofruntime,macros,async,runtime,manual,serde, andasync,runtime.cargo doc -D warningson kio with no features, with poll-only features, and with all features; on moq-net with default features and with none.cargo test -p kio -p kio-macros, doctests included.just rs coroutinesscans (kio: none; moq-net: the three allowed), plus a negative run that confirms the scan catches kio's coroutines withasyncon.sh/rs/net-features.sh: 1279 tests passed.sh/rs/tokio-features.shpassed.--no-default-featureschecks fromjust rs features: moq-relay, moq-cli, moq-bench, moq-boy, and moq-hls/rtmp/rtc with all targets.--all-targetschecks of moq-auth, moq-congestion, moq-ice, moq-quic, moq-shaper, and moq-net-tests.just ci origin/main(with a scratchCARGO_TARGET_DIRandBASH_ENV=/dev/null) passed every module exceptcheck flake. That one fails while building thegithub-runnerVM derivation:unshare: write failed /proc/self/uid_map: Operation not permitted. The cause is this host's sandbox; the PR changes no Nix files. Rust: 10934 tests passed. The first run caught a shellcheck SC1087 insh/rs/coroutines.sh, which is now fixed.quest check --base origin/mainpassed.cargo teston kio-macros (UI cases included) and kio with all features,cargo clippy -p kio -p kio-macros --all-targets --all-features -D warnings,just rs coroutines,quest check, and lone--libchecks of moq-auth (all features), moq-ice, moq-congestion, and moq-quic. moq-auth's failed before the fix withno method named wait found for struct Shared<T>.origin/main3ae6789 (head1702e940):just rs coroutines(kio: none; moq-net: the three allowed),cargo test -p kio -p kio-macros --all-features(UI cases and doctests included),cargo clippy -p kio -p kio-macros --all-targets --all-features -D warnings,cargo clippy -p kio -D warningswith no features and with each ofmacros,async,runtime,manual,serde, andasync,runtime, andquest check --base origin/main.just rs featurespassed every step but its last, the workspace nextest. There, 11070 of 11071 tests passed (rerun with--no-fail-fast). The one failure,moq-relay::integration stack::debug_relay_load_and_run_fit_windows_stack, overflows its 1 MiB stack under--all-features. It fails the same way onmainat 3ae6789 without this PR, and moq-dev/moq#7576 already plans it asquest/m0/test-flakes-2/relay-stack-all-features.md.Review
Codex harness, gpt-6-astra, medium effort (
--deep, because kio's public API changes), againstorigin/main75c48bb:ebd7b35276d8d5ae948b70eb7501815fb2902b69: no findings.398809e3602bc1658ef6ab307e2c16a9b0a66eac(the shellcheck fix and a conflict-free merge oforigin/main): no findings.Head
1f79714e4f42ff065929bf5488471527a902d23c(a conflict-free merge oforigin/main2ebcea5 and the two Pullfrog fixes): local review skipped under the simple-review rule (moq-dev/quest#364). Both fixes are a few lines and touch no public API, wire format, security code, orunsafe: a diagnostic in place of a proc-macro panic, and a cargo feature plus onejust rs featurescheck. The online reviewers cover this head.Head
1702e940966f5929b7f0b695a1c500ffa9240320(a merge oforigin/main3ae6789): local review skipped under the simple-review rule, since the merge is mechanical. Its one conflict was inrs/kio/src/clock/mod.rs's re-exports. The resolution keeps both sides unchanged: main's newpub use random::{Rng, rng, seed};and this PR's#[cfg(feature = "async")] pub use timer::drive;. main's new kio code (the seededclock::rng) and its callers in moq-net, moq-relay, moq-hls, moq-rtmp, moq-tokio, moq-audio, and moq-video add no async kio API and await nothing newly gated. Its only new kioasynccode is a test helper inclock::sim's tests, which builds withsim, andsimalready enablesasync. No online-reviewer thread is open.Pullfrog on
398809e:kio/async: fixed.Ident::new_rawpanics forpoll_selfandpoll__: fixed, and forpoll_1too.Follow-ups
The rewritten quest covers the remaining rollout. Suggested for
/quest-plan: split the quest into children, one each for moq-net's remaining wrappers, the origin front driver poll machine, and each sibling library'sasyncfeature, since each can land on its own.(Written by Claude Opus 5.5)