Skip to content

fix: make handle<T> surface consistently across generators #45

Description

@owenthcarey

Summary

handle<T> (a typed opaque handle whose tag is a struct T) is rendered differently by each generator, and two of the renderings do not compile. The IDL reference says it is "still a uint64_t" at the C ABI, but the emitted header declares it as an opaque struct pointer (weaveffi_<module>_<T>*), and the language wrappers disagree about what a consumer receives.

Observed on main after #44, using the kitchen_sink and edge_cases snapshot fixtures:

Generator handle<Token> surfaces as Status
C header weaveffi_kitchen_Token* (opaque pointer) compiles; contradicts the docs
Dart Token._(result) / token._handle on the Token record class does not compile: Token is a plain data class with no _ constructor or _handle getter
Node .d.ts Token (the record interface itself) compiles but wrong: a pointer is typed as the decoded record
Swift UInt64 compiles
Python int (c_void_p) compiles
Wasm .d.ts number compiles

The Dart failure predates #44 and was never caught because no sample uses handle<T> and nothing compiled the generated Dart before the edge_cases audit.

Reproduction

  1. weaveffi generate crates/weaveffi-cli/tests/fixtures/edge_cases.yml -o out
  2. cd out/dart && dart analyze
  3. See The getter '_handle' isn't defined for the type 'Leaf' and The method '_' isn't defined for the type 'Leaf' at the typedHandleParam wrapper. The same Token._(result) shape appears in the kitchen_sink Dart output.

Expected

One documented answer to "what does a consumer hold for handle<T>?" applied uniformly. Two reasonable designs:

  • Opaque wrapper class per tag. Each language gets a tiny TokenHandle-style class wrapping the pointer, giving the type safety the docs promise. This is what Dart appears to have been reaching for.
  • Plain integer everywhere. Match Swift and Python, and fix the docs' uint64_t claim to agree with the header (or change the header to uint64_t).

Either way, Dart must stop calling members that do not exist, Node must stop typing the handle as the record, and docs/src/reference/idl.md ("Typed handles") must match the header.

Environment

Additional context

Found during the coverage audit in #44. The edge_cases fixture keeps typed_handle_param (handle<Leaf> as both a parameter and a return) so the snapshot diff will show the fix landing in every generator.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions