Problem
The snapshot suite (crates/weaveffi-cli/tests/snapshots.rs) pins the exact text every generator emits for five fixtures, and the conformance harness (conformance/run.sh) compiles and runs real consumers for the seven samples/. Neither checks that the fixtures' output compiles.
That gap matters because the fixtures reach shapes the samples do not: reserved-word identifiers, [T?]? nesting, mutable: true, iter<string>, type-level deprecated, async returning structs, and so on. During #44 a one-off manual pass that fed the edge_cases fixture through each language's compiler or analyzer found seven latent bugs that had shipped in every prior release (a Python SyntaxError, a C header that broke under C++, an invalid C# array creation, a Dart type shadowed by a field, a Wasm .d.ts that failed tsc --strict, and two local-variable collisions). Snapshots alone would have recorded all of them as "expected output".
Proposed solution
Add a CI step that, for every fixture under crates/weaveffi-cli/tests/fixtures/, generates all eleven targets and runs a syntax or type check per language, with no producer library required:
| Target |
Check |
| C |
clang -fsyntax-only -x c weaveffi.h |
| C++ |
clang++ -std=c++17 -fsyntax-only -x c++ weaveffi.hpp |
| Python |
python3 -m py_compile on every .py |
| Node |
node --check index.js; tsc --noEmit --strict --types node types.d.ts |
| Wasm |
node --check weaveffi_wasm.js; tsc --noEmit --strict weaveffi_wasm.d.ts |
| Swift |
swiftc -parse on Sources/WeaveFFI/*.swift |
| Go |
go vet with the C header copied alongside (cgo needs it) |
| Dart |
dart pub get && dart analyze |
| Kotlin |
kotlinc with kotlinx-coroutines on the classpath |
| .NET |
dotnet build |
| Ruby |
ruby -c on every .rb |
The conformance job already installs all of these toolchains, so this fits as a new phase in conformance/run.sh (or a sibling script it calls) rather than a new workflow. Failures should name the fixture, target, and file.
Alternatives considered
- Rely on snapshot review. This is the status quo; it depends on a reviewer spotting
None = 0 in a 2,000-line diff.
- Add every edge shape to a sample. Samples need a real Rust producer for each function, which is a lot of boilerplate for shapes that exist only to stress the generators.
- Write per-language compile tests in Rust. Possible via
std::process::Command, but the toolchain setup already lives in the conformance job and belongs there.
Target(s)
Additional context
Once this lands, #45 (typed handles) will fail the Dart check for kitchen_sink and edge_cases until it is fixed, which is the intended behavior: the fixture keeps the broken shape so the check enforces the fix. Known pre-existing go vet noise ("possible misuse of unsafe.Pointer" on the uintptr-to-pointer pattern) will need either a fix in the Go generator or a -unsafeptr=false flag on that lane.
Problem
The snapshot suite (
crates/weaveffi-cli/tests/snapshots.rs) pins the exact text every generator emits for five fixtures, and the conformance harness (conformance/run.sh) compiles and runs real consumers for the sevensamples/. Neither checks that the fixtures' output compiles.That gap matters because the fixtures reach shapes the samples do not: reserved-word identifiers,
[T?]?nesting,mutable: true,iter<string>, type-leveldeprecated, async returning structs, and so on. During #44 a one-off manual pass that fed theedge_casesfixture through each language's compiler or analyzer found seven latent bugs that had shipped in every prior release (a PythonSyntaxError, a C header that broke under C++, an invalid C# array creation, a Dart type shadowed by a field, a Wasm.d.tsthat failedtsc --strict, and two local-variable collisions). Snapshots alone would have recorded all of them as "expected output".Proposed solution
Add a CI step that, for every fixture under
crates/weaveffi-cli/tests/fixtures/, generates all eleven targets and runs a syntax or type check per language, with no producer library required:clang -fsyntax-only -x c weaveffi.hclang++ -std=c++17 -fsyntax-only -x c++ weaveffi.hpppython3 -m py_compileon every.pynode --check index.js;tsc --noEmit --strict --types node types.d.tsnode --check weaveffi_wasm.js;tsc --noEmit --strict weaveffi_wasm.d.tsswiftc -parseonSources/WeaveFFI/*.swiftgo vetwith the C header copied alongside (cgo needs it)dart pub get && dart analyzekotlincwithkotlinx-coroutineson the classpathdotnet buildruby -con every.rbThe conformance job already installs all of these toolchains, so this fits as a new phase in
conformance/run.sh(or a sibling script it calls) rather than a new workflow. Failures should name the fixture, target, and file.Alternatives considered
None = 0in a 2,000-line diff.std::process::Command, but the toolchain setup already lives in the conformance job and belongs there.Target(s)
Additional context
Once this lands, #45 (typed handles) will fail the Dart check for
kitchen_sinkandedge_casesuntil it is fixed, which is the intended behavior: the fixture keeps the broken shape so the check enforces the fix. Known pre-existinggo vetnoise ("possible misuse of unsafe.Pointer" on the uintptr-to-pointer pattern) will need either a fix in the Go generator or a-unsafeptr=falseflag on that lane.