non-deterministic field ordering in generated builder state types

did:plc:vozr2os4b4sxrxr6opde5js5 opened this Mar 24, 2026 3 comments
did:plc:vozr2os4b4sxrxr6opde5js5 opened Mar 24, 2026

jacquard-codegen produces non-deterministic ordering of fields in the generated builder state types (State trait, Set* structs, members module). Running the same command twice on the same input produces different output:

$ jacquard-codegen --input lexicons --output src
$ cp src/app_bsky/feed/like.rs /tmp/like1.rs
$ jacquard-codegen --input lexicons --output src
$ diff /tmp/like1.rs src/app_bsky/feed/like.rs
116d115
<         type CreatedAt;
117a117
▎     type CreatedAt;
126,132d125
<     ///State transition - sets the created_at field to Set
<     pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>);
...

The generated struct fields and serde attributes are stable, but the builder state machinery (trait associated types, Set* state transition structs, and members marker types) shuffles between runs.

This likely comes from iterating over a HashMap (or similar unordered collection) when generating the required-field tracking code.

This makes it impossible to check generated code into version control and verify it's up to date in CI via git diff --exit-code, which is a common pattern (e.g., protobuf, sqlx).

Version: jacquard-lexgen 0.11.1 (also reproduced on 0.9.5)

No activity yet.

cospan · schematic version control on atproto built on AT Protocol