Skip to content

Refactor reference types in the C/C++ API#13154

Merged
alexcrichton merged 8 commits intobytecodealliance:mainfrom
alexcrichton:refactor-gc-c-api
Apr 21, 2026
Merged

Refactor reference types in the C/C++ API#13154
alexcrichton merged 8 commits intobytecodealliance:mainfrom
alexcrichton:refactor-gc-c-api

Conversation

@alexcrichton
Copy link
Copy Markdown
Member

In updating wasmtime-py to Wasmtime 44 I noticed a few discrepancies in the C API, and then C++ API, in addition to what was found in #13149. Notably we had both wasmtime_exn_t/Exn and
wasmtime_exnref_t/ExnRef. In sorting this out with some deeper fixes in #13149 I got stuck again in the rat's nest of circular definitions of classes in C++. In the end I gave up trying to incrementally improve things and decided to go with a larger refactoring. The goal here is to more cleanly separate out responsibilities and improve how circular definitions in C++ are handled:

  • All reference types now live in their own file. Reference types aren't in a mix of val.h or gc.h or exn.h, but instead each type lives in its own file. This means that gc.h is now gone and is replaced by anyref.h, externref.h, exnref.h, eqref.h, ...

  • C++ class definitions are split into separate headers from their main files. For example there's now wasmtime/_anyref_class.hh instead of just wasmtime/anyref.hh. This new method of resolving circular dependencies has some nice properties where headers that depend on the AnyRef type, for example, include _anyref_class.h. The anyref.h header then is able to include all other headers necessary for defining methods. Notably this means that methods now always live in the header of the type as opposed to sprinkled about in various locations. Note that this is applied to preexisting headers like func.hh and store.hh out of necessity, too.

  • Reference types in the C++ now share core methods via a macro to avoid duplicating code and to ensure they have a uniform API.

  • Some #defines for WASMTIME_FEATURE_GC guards were adjusted in a few locations. For example wasmtime_valraw_t no longer has GC fields when the GC proposal is disabled.

  • Reorganization was reflected on the Rust side as well. This means the previous ref.rs is now broken up into files such as anyref.rs. Some logic of core functions was also deduplicated within the ref_wrapper! macro. The old definitions of wasmtime_exn_t and wasmtime_exnref_t were also both merged.

Overall this PR contains quite a lot of code movement and things were shuffled around, as well as adjustments to the exnref C API (removing duplication). Overall though the API is largely as it was before, although for the C++ API if individual headers are being included some new ones may need to be included to ensure all methods are defined.

My hope is that the end result here is a bit more maintainable, types are easier to modify/extend, there's no longer any soups to deal with in C++, and everything should have a uniform API.

@alexcrichton alexcrichton requested a review from a team as a code owner April 20, 2026 22:01
@alexcrichton alexcrichton requested review from dicej and removed request for a team April 20, 2026 22:01
@github-actions github-actions Bot added the wasmtime:c-api Issues pertaining to the C API. label Apr 21, 2026
Copy link
Copy Markdown
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

LGTM

I think in the few other C++ codebases I've touched, the _foo.hh would be foo.hh and the existing foo.hh would be foo-inlines.hh but I don't really care what color we paint the bikeshed.

Comment thread crates/c-api/include/wasmtime/types/arrayref.h Outdated
Comment thread crates/c-api/include/wasmtime/types/structref.h Outdated
Comment thread crates/c-api/src/anyref.rs Outdated
In updating `wasmtime-py` to Wasmtime 44 I noticed a few discrepancies
in the C API, and then C++ API, in addition to what was found in bytecodealliance#13149.
Notably we had both `wasmtime_exn_t`/`Exn` and
`wasmtime_exnref_t`/`ExnRef`. In sorting this out with some deeper fixes
in bytecodealliance#13149 I got stuck again in the rat's nest of circular definitions of
classes in C++. In the end I gave up trying to incrementally improve
things and decided to go with a larger refactoring. The goal here is to
more cleanly separate out responsibilities and improve how circular
definitions in C++ are handled:

* All reference types now live in their own file. Reference types
  aren't in a mix of `val.h` or `gc.h` or `exn.h`, but instead each type
  lives in its own file. This means that `gc.h` is now gone and is
  replaced by `anyref.h`, `externref.h`, `exnref.h`, `eqref.h`, ...

* C++ class definitions are split into separate headers from their main
  files. For example there's now `wasmtime/_anyref_class.hh` instead of
  just `wasmtime/anyref.hh`. This new method of resolving circular
  dependencies has some nice properties where headers that depend on the
  `AnyRef` type, for example, include `_anyref_class.h`. The `anyref.h`
  header then is able to include all other headers necessary for
  defining methods. Notably this means that methods now always live in
  the header of the type as opposed to sprinkled about in various
  locations. Note that this is applied to preexisting headers like
  `func.hh` and `store.hh` out of necessity, too.

* Reference types in the C++ now share core methods via a macro to avoid
  duplicating code and to ensure they have a uniform API.

* Some `#define`s for `WASMTIME_FEATURE_GC` guards were adjusted in a
  few locations. For example `wasmtime_valraw_t` no longer has GC fields
  when the GC proposal is disabled.

* Reorganization was reflected on the Rust side as well. This means the
  previous `ref.rs` is now broken up into files such as `anyref.rs`.
  Some logic of core functions was also deduplicated within the
  `ref_wrapper!` macro. The old definitions of `wasmtime_exn_t` and
  `wasmtime_exnref_t` were also both merged.

Overall this PR contains quite a lot of code movement and things were
shuffled around, as well as adjustments to the `exnref` C API (removing
duplication). Overall though the API is largely as it was before,
although for the C++ API if individual headers are being included some
new ones may need to be included to ensure all methods are defined.

My hope is that the end result here is a bit more maintainable, types
are easier to modify/extend, there's no longer any soups to deal with in
C++, and everything should have a uniform API.
prtest:full
@alexcrichton
Copy link
Copy Markdown
Member Author

Oh nice! I'll be honest in that I don't really have much experience in C++ codebases. I'm going to flag this for merge mostly out of inertia, but I'm also happy to adjust to that pattern next time I'm in these parts.

@alexcrichton alexcrichton enabled auto-merge April 21, 2026 14:43
@alexcrichton alexcrichton added this pull request to the merge queue Apr 21, 2026
Merged via the queue into bytecodealliance:main with commit 06432bd Apr 21, 2026
177 checks passed
@alexcrichton alexcrichton deleted the refactor-gc-c-api branch April 21, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasmtime:c-api Issues pertaining to the C API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants