Skip to content

Rec group builder#13687

Open
somdoron wants to merge 2 commits into
bytecodealliance:mainfrom
somdoron:rec-group-builder
Open

Rec group builder#13687
somdoron wants to merge 2 commits into
bytecodealliance:mainfrom
somdoron:rec-group-builder

Conversation

@somdoron

Copy link
Copy Markdown

Implements the embedder API requested in issue #10176.

Embedders can currently only build one-off struct/array/func types, so types that reference
themselves or each other can't be constructed directly. This adds RecGroupBuilder: declare
kind-typed labels, use them as forward references, and build() the whole recursion group at
once. It lowers to module-canonical WasmSubTypes and reuses the existing rec-group
registration path.

Also fixes an unrelated pre-existing bug in StorageType::is_val_type (matched I16 instead of
ValType), in its own commit.

It previously matched the `I16` variant instead of `ValType`, so it
returned the wrong answer for every storage type. The method is
otherwise unused inside the tree, which is why this went unnoticed.
@somdoron somdoron requested review from a team as code owners June 18, 2026 13:08
@somdoron somdoron requested review from alexcrichton and pchickey and removed request for a team June 18, 2026 13:08
Adds `RecGroupBuilder`, which lets embedders declare kind-typed labels
(`PendingStructId`/`PendingArrayId`/`PendingFuncId`), use them as forward
references while defining other types via a small build-time "template"
family, and register the whole group at once with `build()`. This makes
it possible to construct self-referential and mutually-recursive
struct/array/func types directly from the embedder API, which previously
required plucking such types out of a module's imports/exports.

The builder lowers its members to module-canonical `WasmSubType`s (using
0-based `Module` indices for intra-group references and `Engine` indices
for already-registered types) and reuses the existing rec-group
registration path, so hash-consing, runtime canonicalization, supertype
lists, and GC layouts all come for free.

Implements the embedder API requested in bytecodealliance#10176.
@somdoron somdoron force-pushed the rec-group-builder branch from e4e67d9 to ff45908 Compare June 18, 2026 13:19
@github-actions github-actions Bot added wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:docs Issues related to Wasmtime's documentation labels Jun 18, 2026
@fitzgen fitzgen added the wasm-proposal:gc Issues with the implementation of the gc wasm proposal label Jun 18, 2026
@fitzgen fitzgen requested review from fitzgen and removed request for alexcrichton and pchickey June 18, 2026 16:57
@fitzgen

fitzgen commented Jun 18, 2026

Copy link
Copy Markdown
Member

@somdoron given that you just posted an AI plan verbatim in this PR's associated issue, I am assuming you also used AI to implement this PR. Can you confirm that you have already reviewed the AI tool's work in detail before posting it here and asking reviewers to spend their time on it? And are you taking full responsibility for the code in this PR?

https://github.com/bytecodealliance/governance/blob/main/AI_TOOL_POLICY.md

@somdoron

Copy link
Copy Markdown
Author

@fitzgen I confirmed that I reviewed the AI tool. I reviewed the code, and I'm taking full responsibility for the code in this PR. The PR is for a real problem I'm suffering from, and is focused and small.

@github-actions

Copy link
Copy Markdown

Subscribe to Label Action

cc @fitzgen

Details This issue or pull request has been labeled: "wasm-proposal:gc", "wasmtime:api", "wasmtime:docs"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: wasm-proposal:gc

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@fitzgen fitzgen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

First of all, I want to say that this feature is going to involve a lot of API design, and probably won't land super quickly because of that. If you really need to be able to define rec groups in the host now, you can do that via building Modules (either via WAT strings or via wasm_encoder) that define the rec groups you need and export a global of each of the rec groups types so you can exfiltrate the GlobalType and the global type's ValType on the host via Module::exports. So that should unblock you for the time being, if necessary.

Some high-level thoughts on the design:

  • I don't think we need to distinguish between pending structs versus pending arrays at the type level. I don't think it is buying us much in terms of correctness by construction or whatever, but it makes ramping up on the API that much harder.

  • I don't love adding FieldTemplate/HeapTypeTemplate/etc... types to Wasmtime's public API. I think we could avoid that (and also not force callers to construct slices of them, potentially allocating when they otherwise wouldn't) by having a struct type builder that borrows the rec group builder and exposes a method to define fields one at a time, something like this:

    impl RecGroupBuilder<'_> {
        pub fn define_struct(&mut self, ty: PendingType) -> StructTypeBuilder<'_> { ... }
    }
    
    pub struct StructTypeBuilder<'a> {
        rec_group: &'a mut RecGroupBuilder,
        // ...
    }
    
    impl StructTypeBuilder<'_> {
        /// Define a normal, non-forward-reference field.
        pub fn field(&mut self, ty: FieldType) { ... }
    
        /// Define a field that is a forward reference to another type defined in this rec group.
        pub fn forward_ref_field(&mut self, ty: PendingType) -> ForwardRefFieldBuilder<'_> { ... }
    }
    
    pub struct ForwardRefFieldBuilder<'a> {
        parent: StructOrArrayTypeBuilder<'a>,
        // ...
    }
    
    impl ForwardRefFieldBuilder<'_> {
        pub fn nullable(&mut self, nullable: bool) -> &mut Self { ... }
    
        pub fn shared(&mut self, shared: bool) -> &mut Self { ... }
    
        pub fn finish(self) -> &mut StructTypeBuilder<'_> { ... }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasm-proposal:gc Issues with the implementation of the gc wasm proposal wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:docs Issues related to Wasmtime's documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants