Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bench/build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ Measured on 2026-10-25 and 2026-10-26 on a busy 32-CPU host, in billions of inst
## Cranelift for moq's CI

Recommended on 2026-10-25: moq's CI keeps building its tests with LLVM, since 42 of its 5418 tests fail under Cranelift.
At the pin [#646](https://github.com/moq-dev/rust2/pull/646) moved to on 2026-11-07, 58 of 6379 fail: 27 that catch a panic and 31 on the intrinsic ([cranelift-unwind](/quest/m3/cranelift-unwind.md)). The numbers below are the 2026-10-25 run's.

- 23 catch a panic, which the Cranelift backend that ships with nightly cannot unwind: it builds every panic as an abort (unwinding is a flag on cg_clif's own build, off by default: [rustc_codegen_cranelift#1567](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1567)).
- 19 abort on an x86 SIMD intrinsic it does not implement, `llvm.x86.sse2.pmulhu.w` ([rustc_codegen_cranelift#171](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171)). moq's CI runs on aarch64, whose intrinsics this x86 benchmark does not try.
Expand Down
2 changes: 1 addition & 1 deletion bench/ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Native libraries are `release` (fat LTO, `strip = "debuginfo"`, as moq-ffi ships
| slice, Swift: UniFFI / BoltFFI | 3 / 2 | 101 / 51 KiB | 14 / 8 KiB |
| moq-ffi, UniFFI: Python / Kotlin / Swift | 1 / 1 / 3 | 653 / 914 / 684 KiB | 66 / 73 / 72 KiB |

Browser builds use opt-level z after wasm-bindgen and no wasm-opt, as moq-wasm ships; the stripped columns drop the `name` section.
Browser builds use opt-level z after wasm-bindgen and no wasm-opt, as moq-wasm shipped before moq removed it; the stripped columns drop the `name` section.

| browser module | .wasm as built | .wasm stripped | stripped, gzip | JS glue | JS glue, gzip |
|---|---|---|---|---|---|
Expand Down
4 changes: 2 additions & 2 deletions ffi/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# rust2-ffi

A rustc driver that exports a crate's `pub` API as a C ABI and a C header, with no
attributes in the Rust source. It replaces [the UniFFI fork](../uniffi/README.md) for moq,
starting from C, which every other language's generator will build on.
attributes in the Rust source. It replaces [the UniFFI fork](../uniffi/README.md) for moq.
Every language's generator but Python's builds on the C ABI.

```bash
rust2-ffi --config ffi.toml (--out dir | --census dir) [--manifest-path Cargo.toml] [-- cargo args]
Expand Down
16 changes: 8 additions & 8 deletions quest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ grouped into milestones ordered by priority.
## Plan

m0 holds urgent fixes. m1 is the work with a consumer waiting on it now:
the exporter that replaces the UniFFI fork (moq skips switching to the fork), and
the fork's perf work. m2 is research: the TypeScript translator, which moq's
browser package adopts once it matches the handwritten one, and the fork's gated or
speculative work. m3
holds the build-speed tracks, which the
[build-speed benchmark](/bench/build/README.md) rescopes before they start,
and speculative work. m4 holds long-term research.
the exporter that replaces the UniFFI fork (moq skips switching to the fork). m2 is
research: the TypeScript translator, which moq's browser package adopts once it matches
the handwritten one, and the fork's gated or speculative work. m3 holds work that waits
on evidence or has no consumer yet: the build-speed tracks, which the
[build-speed benchmark](/bench/build/README.md) rescopes before they start, and the
parts of std and the translators' features no consumer calls yet. m4 holds long-term
research.

Decided with the maintainer on 2026-10-23, when rust2 was planned from moq
([moq-dev/moq#6578](https://github.com/moq-dev/moq/pull/6578)):
Expand All @@ -32,5 +32,5 @@ Decided with the maintainer on 2026-10-23, when rust2 was planned from moq
- [m0: immediate priorities](/quest/m0/README.md) - urgent fixes
- [m1: consumers waiting](/quest/m1/README.md) - the exporter that replaces the UniFFI fork for moq
- [m2: research](/quest/m2/README.md) - the TypeScript translator's spikes and features toward moq-net's model, and the fork's gated work
- [m3: deferred](/quest/m3/README.md) - the pure-Rust profile and upstream's build-speed levers, measured by the benchmark
- [m3: deferred](/quest/m3/README.md) - upstream's build-speed levers, measured by the benchmark, and the std gaps and translator features no consumer calls yet
- [m4: long-term research](/quest/m4/README.md) - ideas no consumer needs yet, such as a rustc and cargo fork
2 changes: 1 addition & 1 deletion quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fork stays in maintenance and keeps building moq's bindings until then; its feat
are folded into the [exporter's](/quest/m1/ffi-export/README.md). The
[binding benchmark](/bench/ffi/README.md) continues as the exporter's baseline.

Decided 2026-11-02 (maintainer, moq's /quest-unblock): the fork is not published to crates.io. moq skips it and switches straight to the exporter ([moq's switch](https://github.com/moq-dev/moq/blob/main/quest/m2/ffi-exporter.md)), so publishing would only commit permanent `rust2-*` names to code already slated for retirement. moq keeps its own pinned generator forks until the exporter is ready.
Decided 2026-11-02 (maintainer, moq's /quest-unblock): the fork is not published to crates.io. moq skips it and switches straight to the exporter ([moq's switch](https://github.com/moq-dev/moq/blob/main/quest/m3/ffi-exporter.md)), so publishing would only commit permanent `rust2-*` names to code already slated for retirement. moq keeps its own pinned generator forks until the exporter is ready.

## Required

Expand Down
4 changes: 2 additions & 2 deletions quest/m1/ffi-export/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Decided with the maintainer on 2026-11-01: the Swift, Python, Go, and Dart gener
independent and unranked, and each generates the crate's own API in its language's idiom, as
Kotlin does. Only Python skips the C ABI, since a CPython extension calls about 40 times faster
than `ctypes`; the others call C natively. moq's packages switch to them in moq's own
[quest](https://github.com/moq-dev/moq/blob/main/quest/m2/uniffi-fork.md).
[quest](https://github.com/moq-dev/moq/blob/main/quest/m3/ffi-exporter.md).

Decided with the maintainer on 2026-11-02
([moq-dev/rust2#460](https://github.com/moq-dev/rust2/pull/460)): the RSS glibc's per-thread
Expand All @@ -61,5 +61,5 @@ names and defaults, and fails the export on a public item it cannot export.

## Required

- [Sessions on sans-IO QUIC](/quest/m1/ffi-export/session-quic.md) - bindings move UDP datagrams and drive the session's poll themselves, over moq's runtime-free QUIC driver once it lands
- [Every public item exports](/quest/m1/ffi-export/refusals/README.md) - the census lists no refusals and `ffi.toml` is deleted, so the exporter reads no config
- [Sessions on sans-IO QUIC](/quest/m1/ffi-export/session-quic.md) - bindings move UDP datagrams and drive the session's poll themselves, over moq's runtime-free QUIC driver once it lands
22 changes: 11 additions & 11 deletions quest/m1/ffi-export/refusals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@
`just ffi census` lists no refusals at the moq pin and `ffi.toml` is deleted: the exporter
reads no config, and an item it cannot export fails the export with a span.

What stays here once every child has merged:

- The stand-in facade (`just ffi standin`) re-exports only the session side moq-ffi ships
from moq-tokio: `Client`, `Server`, `server::Request`, `connect::Config`,
`listen::Config`, `quic::Config`, `Connection`, `Transport`, `Log`, `tls`, `panic`, and
the errors, in place of `pub use ::moq_tokio::*;`.
- `ffi/moq/ffi.toml`, `--config`, and `ffi/src/config.rs` are deleted, and `ffi/README.md`
and the recipes stop naming them.
What stays here once every child has merged: `ffi/moq/ffi.toml`, the `--config` flag,
`RUST2_FFI_CONFIG`, and `config.rs`'s `Config` and `exclude` are deleted, with the
fixtures' `ffi/fixtures/api/ffi.toml` and `ffi/fixtures/reject/ffi.toml` and the exclude
tests in `ffi/tests/fixtures.rs`; `ffi/README.md` and the recipes stop naming them.
`config.rs`'s `Package` and environment constants stay.

## Plan

Expand All @@ -38,6 +35,8 @@ Decided with the maintainer on 2026-11-07, from
binding calls; the sans-IO driver bindings use instead is
[session-quic](/quest/m1/ffi-export/session-quic.md). Children leave the moq-tokio items
outside that session side alone, since narrowing the stand-in drops them.
- ✅ Narrowing the stand-in is the first child, so the others count only what stays
(decided in the quest audit). Rejected: narrowing last, as this epic's own work.
- ✅ What C can never hold, an object no export returns or lends to a closure, or a generic
type no export instantiates, is left out of the bindings and kept listed in the census.
Rejected: refusing them, which would make moq add constructors it has no use for.
Expand All @@ -47,19 +46,20 @@ Decided with the maintainer on 2026-11-07, from
The census at moq `ffcb7cd9` (2026-11-07) refuses 1111 items, which `ffi/moq/ffi.toml`'s
300 excludes hide by naming whole modules. About 790 lie in crates moq re-exports whole.
The other 324 are moq's own, 107 of them in moq-tokio (61 under `quic`); each child gives
its construct's count, and an item counts under every construct it hits. 17 more refuse
its construct's count, and an item counts under every construct it hits. The counts
include the moq-tokio items narrowing drops; each child measures again once it lands. 17 more refuse
only because a type they name is refused, and clear with it.

Public API: the exporter's command line and the C API of every item that exports.

## Required

- [The stand-in exports only moq-tokio's session side](/quest/m1/ffi-export/refusals/narrow-standin.md) - `just ffi standin` names the session items moq-ffi ships in place of `pub use ::moq_tokio::*;`
- [Whole-crate re-exports are refused with one span](/quest/m1/ffi-export/refusals/reexports.md) - the exporter stops at a `pub use` of a crate root, turning about 790 refusals into one per re-export
- [Generic parameters and traits export](/quest/m1/ffi-export/refusals/generics.md) - `Client::connect`'s `Boxable`, futures and readers as parameters, trait objects, associated types, and callbacks
- [Standard and common types export by role](/quest/m1/ffi-export/refusals/std-types.md) - maps, sets, errors, `NonZero`, addresses, instants, sockets, levels, JSON maps, and iterator adapters
- [Poll and Context export](/quest/m1/ffi-export/refusals/poll.md) - a `poll_*` with no async twin takes a waker, as futures' polls do
- [Borrow shapes export](/quest/m1/ffi-export/refusals/borrows.md) - `Option<&T>`, `&mut` buffers, `&Bytes`, `Arc<T>`, `'static` borrows, and borrowed returns that are not `Clone`
- [Small shapes export](/quest/m1/ffi-export/refusals/small-shapes.md) - `u128`, arrays, const generics, unit and `Result` off a return, `!`, empty enums, and what is not `Send`
- [What C can never hold is left out and listed](/quest/m1/ffi-export/refusals/unholdable.md) - objects no export returns or lends to a closure, and generics no export instantiates leave the bindings but stay in the census
- [moq drops its whole-crate re-exports](/quest/m1/ffi-export/refusals/moq-reexports.md) - the moq pin moves past the change, and the census has no re-export refusal left
- [moq's types are reachable from their crate root](/quest/m1/ffi-export/refusals/moq-unreachable.md) - the moq pin moves past moq-mux's `Guard` and moq-quic's `Side` fixes
- [Bump the moq pin past its re-export and reachability fixes](/quest/m1/ffi-export/refusals/moq-pin.md) - the census has no whole-crate re-export refusal and no unreachable type of moq's own
46 changes: 46 additions & 0 deletions quest/m1/ffi-export/refusals/moq-pin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# [XS] Bump the moq pin past its re-export and reachability fixes

## Goal

The moq pin moves to a revision whose crates re-export no whole crate, moq's own included,
and where every type a facade export names is reachable from the facade's root. `just ffi
census` there lists no whole-crate re-export refusal and no "type not reachable from the
crate root" refusal of moq's own (18 at moq `ffcb7cd9`).

## Plan

Decided with the maintainer on 2026-11-07, from
[moq-dev/rust2#655](https://github.com/moq-dev/rust2/pull/655) and
[moq-dev/moq#8233](https://github.com/moq-dev/moq/pull/8233): ✅ moq re-exports no whole
crate, its own included: the ten first listed (moq-net's `bytes` and `kio`; `rustls` in
moq-quic, moq-rtmp, and moq-tokio; moq-tokio's `notify`, `usage_rs`, and `http`;
moq-uring's `http`; moq-mux's `mp4_atom`), hang's and moq-tokio's `pub use moq_net;`,
moq-tokio's `moq_congestion as congestion`, `web_transport_proto as proto` in moq-tokio and
moq-uring, and the rest, such as `axum`, `url`, `object_store`, moq-video's platform crates,
`jni`, and `tikv_jemallocator`. moq-quic-unused-surface names the moq-quic items it needs
instead of adding `pub use moq_quic;`. Each whole-crate re-export makes that crate's whole
API part of moq's, so any breaking release of it breaks moq's semver; moq re-exports by
name only the items its signatures need, or wraps them. Rejected: only the ten; only
third-party crates.

At `ffcb7cd9`, `container::Producer::modify` returns moq-mux's
`container::producer::Guard`, in a private module (16 refusals), and moq-tokio's
`quic::driver` re-exports moq-quic's `stream::Id` but not the `Side` its `new` and
`initiator` take (2). Both are moq's to fix; the stand-in's narrowing to moq-tokio's
session side also drops `quic::driver`.

Decided with the maintainer on 2026-11-07, in the quest audit: one pin bump for both, since
each is an XS bump of the same pin line. Rejected: one bump per moq quest.

Then bump the pin in `ts/fixtures/model/Cargo.toml`, which `ts/justfile`'s `moq_rev` reads,
and report the census before and after.

## Waiting

- moq-dev/moq: [quest/m2/api-shape/reexports.md](https://github.com/moq-dev/moq/blob/main/quest/m2/api-shape/reexports.md),
planned in [moq-dev/moq#8233](https://github.com/moq-dev/moq/pull/8233), drops every
whole-crate re-export, moq's own included, and re-exports `Guard` from `container`. Done
once that quest is gone from moq's `main` and the census at its head lists no whole-crate
re-export.
- moq-dev/moq: [quest/m2/moq-quic-unused-surface.md](https://github.com/moq-dev/moq/blob/main/quest/m2/moq-quic-unused-surface.md)
removes `stream::Id::{new, initiator}`. Done once that quest is gone from moq's `main`.
32 changes: 0 additions & 32 deletions quest/m1/ffi-export/refusals/moq-reexports.md

This file was deleted.

24 changes: 0 additions & 24 deletions quest/m1/ffi-export/refusals/moq-unreachable.md

This file was deleted.

27 changes: 27 additions & 0 deletions quest/m1/ffi-export/refusals/narrow-standin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# [XS] The stand-in exports only moq-tokio's session side

## Goal

The stand-in facade (`just ffi standin`, in `ffi/justfile`) re-exports only the session
side moq-ffi ships from moq-tokio: `Client`, `Server`, `server::Request`,
`connect::Config`, `listen::Config`, `quic::Config`, `Connection`, `Transport`, `Log`,
`tls`, `panic`, and the errors, in place of `pub use ::moq_tokio::*;`. `ffi/moq/ffi.toml`
loses the excludes that only hid items outside it, and the census at the pin reports the
refusals before and after, per crate.

## Plan

Decided with the maintainer on 2026-11-07, from
[moq-dev/rust2#655](https://github.com/moq-dev/rust2/pull/655): ✅ the stand-in re-exports
only that session side. Rejected: all of moq-tokio, whose tokio QUIC driver, CLI helpers,
worker groups, and listeners no binding calls; bindings drive the sans-IO driver of
[session-quic](/quest/m1/ffi-export/session-quic.md) instead.

Decided with the maintainer on 2026-11-07, in the quest audit: ✅ this lands first, so the
other children count only what stays. Narrowing drops moq-tokio's `rustls`, `notify`,
`congestion`, `cli::usage_rs`, and `quic::web`'s `http` and `proto` re-exports, and
`quic::driver`'s `Side` refusals. Every item named exists at moq `ffcb7cd9`
(`rs/moq-tokio/src/lib.rs`). Update the counts in the
[epic](/quest/m1/ffi-export/refusals/README.md) and its children from the new census.

Public API: the stand-in's exports, which the census and the bindings' fixtures read.
11 changes: 8 additions & 3 deletions quest/m1/ffi-export/refusals/reexports.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ skipping them silently, as rustdoc does; exporting their whole APIs.
The rule goes by form, with no list and no exception for moq's own crates: hang's and
moq-tokio's `pub use moq_net;` refuse too, although the census folds them into the root's
moq-net today. A facade's own named re-exports from a crate, such as the stand-in's
`pub use kio::{Park, Waiter, ...};`, are not whole-crate and export as now.
[moq-reexports](/quest/m1/ffi-export/refusals/moq-reexports.md) waits on moq to drop them.
`pub use kio::{Park, Waiter, ...};`, are not whole-crate and export as now. So does a glob
of a crate's root, such as the stand-in's `pub use moq_net::*;`: it re-exports that crate's
items, not the crate as a module (decided with the maintainer on 2026-11-07, in the quest
audit: "we probably need to support re-exports", while moq re-exports only the items it
needs, not all of `rustls`). [moq-pin](/quest/m1/ffi-export/refusals/moq-pin.md) waits on
moq to drop the whole-crate ones.

Document the rule in `ffi/README.md` beside the other refusals, and test it on a fixture
that re-exports a crate whole and by rename.
that re-exports a crate whole, by rename, and by a glob of its root, the last exporting its
items.
Loading