Skip to content

fix(codegen): emit valid, bindable WIT — kebab idents + defined types (#254)#255

Open
avrabe wants to merge 2 commits into
mainfrom
fix/codegen-wit-valid-idents-types
Open

fix(codegen): emit valid, bindable WIT — kebab idents + defined types (#254)#255
avrabe wants to merge 2 commits into
mainfrom
fix/codegen-wit-valid-idents-types

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented Jun 2, 2026

Fixes #254spar codegen --format wit emitted WIT that wasm-tools / wit-bindgen reject, so the generated interface couldn't be bound (broke the spar-generates-WIT workflow on the wohl Matter seam).

Root causes

  1. Invalid identifiers. The WIT generator reused sanitize_ident, which produces Rust snake_case — but WIT is kebab-case. Package wohl_matter:matter was the first hard error; funcs like on-message_in mix a hyphen prefix with an underscore (doubly invalid).
  2. Undefined types. Ports referenced types (mattermessage, monotonictime, …) that were never defined, and emitted bytes, which isn't a WIT primitive.

Fix

  • New wit_ident(): kebab-case WIT identifiers — separators → hyphens, leading-digit words letter-prefixed (WIT words must start with a letter), WIT keywords %-escaped. Used for package / interface / world / func / type / export names.
  • Emit type <name> = list<u8>; for every data type a port references so the interface resolves; untyped ports use list<u8> (valid primitive) instead of non-primitive bytes.
  • Regression guard: a test parses the generated WIT with wit-parser (Resolve::push_str errors on bad idents or undefined types), plus wit_ident unit tests covering the exact codegen --format wit emits unbindable WIT: invalid identifiers (underscores) + undefined types #254 identifiers.

Before → after (same model)

// before (rejected)            // after (valid)
package wohl_matter:matter;     package wohl-matter:bridge;
on-message_in: func() ...       type mattermessage = list<u8>;
... mattermessage (undefined)   on-message-in: func() -> option<mattermessage>;

Verification

Follow-up (noted, out of scope)

Per-type scalar-size fidelity (8-byte Data_Sizeu64, etc., rather than list<u8> for everything) needs scope access threaded into the generator; tracked for a later change. This PR makes the output valid and bindable, which is the blocking issue.

🤖 Generated with Claude Code

…#254)

`spar codegen --format wit` emitted WIT that wasm-tools / wit-bindgen
reject, so the generated interface could not be bound. Two causes:

1. Invalid identifiers. The WIT generator reused `sanitize_ident`, which
   produces Rust `snake_case` (underscores) — invalid in WIT, which is
   kebab-case. Package `wohl_matter:matter` and funcs like `on-message_in`
   (hyphen+underscore) failed `wasm-tools component wit` outright.
2. Undefined types. Ports referenced data types (`mattermessage`, …) that
   were never defined, and used `bytes`, which is not a WIT primitive.

Fix:
- Add `wit_ident()` — kebab-case WIT identifiers (separators -> hyphens,
  leading-digit words letter-prefixed, WIT keywords `%`-escaped) — and use
  it for package / interface / world / func / type / export names.
- Emit a `type <name> = list<u8>;` alias for every data type a port
  references, so the interface resolves. Untyped ports use `list<u8>`
  (a valid primitive) instead of the non-primitive `bytes`. Per-type
  scalar-size refinement (8 bytes -> u64, etc.) needs scope access and is
  a tracked follow-up.
- Add a regression guard that parses the generated WIT with `wit-parser`
  (Resolve::push_str — errors on bad idents OR undefined types), plus
  kebab-case unit tests for the exact #254 identifiers.

Verified end-to-end: `wasm-tools 1.243.0 component wit` now round-trips the
generated file (was: `error: invalid character in identifier '_'`).

Closes #254.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Rivet verification gate

20/20 passed

count
Passed 20
Failed 0
Skipped (no steps) 0

Filter: (and (= type "feature") (or (has-tag "v093") (has-tag "v0100")))

Failed artifacts

(none)

Updated automatically by tools/post_verification_comment.py. Source of truth: artifacts/verification.yaml.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 98.80952% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/spar-codegen/src/wit_gen.rs 98.80% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

cargo fmt — no behavior change. (Format CI check.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

codegen --format wit emits unbindable WIT: invalid identifiers (underscores) + undefined types

1 participant