Skip to content

fix: render macro-generated items from rustdoc JSON - #421

Merged
soothfast-bot[bot] merged 10 commits into
masterfrom
fix/macro-generated-surface
Nov 14, 2026
Merged

soothfast-bot[bot] merged 10 commits into
masterfrom
fix/macro-generated-surface

Conversation

@Verdenroz

Copy link
Copy Markdown
Owner

What changed

A public item generated by a macro_rules! invocation now appears in the API surface under its own name, with a declaration rebuilt from its rustdoc JSON item. Its fingerprint is taken from that declaration and its doc comment. Closes #364.

Why

rustdoc gives a macro-generated item the span of the macro call. The surface took the declaration from the span text up to the first { or ;, so every such item rendered as the call, for example a heading define_batch_response! { } with no body, and the item's real name appeared nowhere. The fingerprint was the call-site text as well, so editing the macro body changed the generated item without marking it as changed.

An item whose span is its own declaration takes the path it took before, and its fingerprint and signature are unchanged.

How was this tested

  • cargo fmt --all -- --check: passed.
  • cargo clippy --workspace --all-targets -- -D warnings: passed.
  • cargo soothfast test --all-features: 3 of 11 packages selected, 5 binaries run, 0 failed.
  • cargo test -p soothfast-docs surface: 26 passed. The 18 existing surface tests pass unchanged, and a new one pins an ordinary struct's fingerprint to fnv1a of its normalized span text.
  • New tests cover detection, two documents that differ only in JSON ids giving one fingerprint, and a field type or doc change giving another.
  • Ran docs reference on a crate whose items come from two macros, against real rustdoc JSON. It rendered pub struct BatchQuotes { pub quotes: Vec<String> }, pub enum Kind { A, B }, pub struct Pair(pub u8, pub String) and pub const fn free(x: &mut i32) -> i32, each with its doc comment, and left an ordinary struct as it was.
  • git diff origin/master -- soothfast.lock soothfast-gate.lock is empty.
  • Not run: a comparison of every fingerprint of a large real crate before and after.

What the rebuilt declaration leaves out: generic bounds and where clauses, enum variant payloads, and the types of constants, statics and aliases. Types it cannot render (dyn, impl, raw and function pointers, qualified paths) print as _. An invocation that names the item inside its own parentheses, such as make!(Foo);, is still treated as a declaration and renders as the call.

Checklist

  • make check passes (fmt, clippy -D warnings, cargo test --workspace)
  • make gate BASE=master passes, or any intentional cost change is explained above
  • Tests added/updated for new behavior (not required for docs/CI-only changes)
  • Public API items have /// doc comments
  • No new dependency, or its justification is included above (see Dependency Policy)
  • Docs (README.md, docs/, soothfast:bind/soothfast:claim markers) updated if behavior changed

- A macro call's span names no item, so the surface listed the call
- Fingerprint hashes the rendered declaration and docs, never JSON ids
@Verdenroz Verdenroz added soothfast:merge Merge once the required checks pass soothfast:update Keep this branch up to date with the default branch labels Nov 14, 2026
@soothfast-bot
soothfast-bot Bot enabled auto-merge (squash) November 14, 2026 00:57
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:00 Active
@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-registry

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: bench binaries identical (code and data match) — no measurable change possible
gate: 2/2 items run code a stored measurement covers, measuring 0
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_registry::bench_fnv1a instructions 245786.0 -> 245786.0 (+0.0%)
ok    soothfast_registry::bench_fnv1a callgrind_ir 245786.0 -> 245786.0 (+0.0%)
ok    soothfast_registry::bench_fnv1a walltime_median_ns 81494.3 -> 81494.3 (+0.0%)
ok    soothfast_registry::bench_fnv1a allocs 0 -> 0 (allowed <= 0)
ok    soothfast_registry::bench_fnv1a alloc_bytes 0 -> 0 (allowed <= 0)
ok    soothfast_registry::bench_yield_chain instructions 585.0 -> 585.0 (+0.0%)
ok    soothfast_registry::bench_yield_chain callgrind_ir 585.0 -> 585.0 (+0.0%)
ok    soothfast_registry::bench_yield_chain walltime_median_ns 139.3 -> 139.3 (+0.0%)
ok    soothfast_registry::bench_yield_chain allocs 1 -> 1 (allowed <= 1)
ok    soothfast_registry::bench_yield_chain alloc_bytes 24 -> 24 (allowed <= 25)
ok    soothfast_registry::bench_yield_chain polls 9 -> 9 (allowed <= 9)
ok    soothfast_registry::bench_yield_chain wakes 8 -> 8 (allowed <= 8)
ok    soothfast_registry::bench_fnv1a assert alloc: allocs 0 <= 0
ok    soothfast_registry::bench_fnv1a assert complexity: claimed O(n); growth drift x0.99 over sizes [1024, 8192, 65536] (limit x2.5)
ok    soothfast_registry::bench_yield_chain assert alloc: allocs 1 <= 1
gate: passed (2 item(s))

@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-report

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: seeded 11 dependency units (19.6 MiB) from HEAD's target dir in 0.0s
gate: bench binaries identical (code and data match) — no measurable change possible
gate: 1/1 items run code a stored measurement covers, measuring 0
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_report::bench_perf_table instructions 8487147.0 -> 8487147.0 (+0.0%)
ok    soothfast_report::bench_perf_table callgrind_ir 8487147.0 -> 8487147.0 (+0.0%)
ok    soothfast_report::bench_perf_table walltime_median_ns 656933.0 -> 656933.0 (+0.0%)
ok    soothfast_report::bench_perf_table allocs 8205 -> 8205 (allowed <= 8615)
ok    soothfast_report::bench_perf_table alloc_bytes 473941 -> 473941 (allowed <= 497638)
ok    soothfast_report::bench_perf_table assert complexity: claimed O(n); growth drift x0.95 over sizes [64, 256, 1024] (limit x2.5)
gate: passed (1 item(s))

@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-measure

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: bench binaries identical (code and data match) — no measurable change possible
gate: 2/2 items run code a stored measurement covers, measuring 0
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_measure::bench_summarize instructions 4515542.0 -> 4515542.0 (+0.0%)
ok    soothfast_measure::bench_summarize callgrind_ir 4515542.0 -> 4515542.0 (+0.0%)
ok    soothfast_measure::bench_summarize walltime_median_ns 246466.0 -> 246466.0 (+0.0%)
ok    soothfast_measure::bench_summarize allocs 4 -> 4 (allowed <= 4)
ok    soothfast_measure::bench_summarize alloc_bytes 524288 -> 524288 (allowed <= 550502)
ok    soothfast_measure::bench_sweep_evaluate instructions 243.0 -> 243.0 (+0.0%)
ok    soothfast_measure::bench_sweep_evaluate callgrind_ir 243.0 -> 243.0 (+0.0%)
ok    soothfast_measure::bench_sweep_evaluate walltime_median_ns 11.4 -> 11.4 (+0.0%)
ok    soothfast_measure::bench_sweep_evaluate allocs 0 -> 0 (allowed <= 0)
ok    soothfast_measure::bench_sweep_evaluate alloc_bytes 0 -> 0 (allowed <= 0)
ok    soothfast_measure::bench_summarize assert alloc: allocs 4 <= 8
ok    soothfast_measure::bench_summarize assert complexity: claimed O(n log n); growth drift x0.99 over sizes [1024, 4096, 16384] (limit x2.5)
ok    soothfast_measure::bench_sweep_evaluate assert alloc: allocs 0 <= 0
gate: passed (2 item(s))

@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-docs

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: seeded 11 dependency units (19.6 MiB) from HEAD's target dir in 0.1s
gate: reusing a run measured from the same merge-base binary
gate: reusing HEAD's own run, measured from binary 78b06a96e4572c19
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_docs::bench_claim_parse instructions 2126.0 -> 2126.0 (+0.0%)
ok    soothfast_docs::bench_claim_parse callgrind_ir 2126.0 -> 2126.0 (+0.0%)
ok    soothfast_docs::bench_claim_parse walltime_median_ns 191.1 -> 191.1 (+0.0%)
ok    soothfast_docs::bench_claim_parse allocs 3 -> 3 (allowed <= 3)
ok    soothfast_docs::bench_claim_parse alloc_bytes 34 -> 34 (allowed <= 35)
ok    soothfast_docs::bench_markdown_scan instructions 5066850.0 -> 5066850.0 (+0.0%)
ok    soothfast_docs::bench_markdown_scan callgrind_ir 5066850.0 -> 5066850.0 (+0.0%)
ok    soothfast_docs::bench_markdown_scan walltime_median_ns 428575.0 -> 428575.0 (+0.0%)
ok    soothfast_docs::bench_markdown_scan allocs 4114 -> 4114 (allowed <= 4319)
ok    soothfast_docs::bench_markdown_scan alloc_bytes 338400 -> 338400 (allowed <= 355320)
ok    soothfast_docs::bench_claim_parse assert p99: p99 199ns <= 50000ns
ok    soothfast_docs::bench_markdown_scan assert complexity: claimed O(n); growth drift x1.05 over sizes [512, 2048, 8192] (limit x2.5)
gate: passed (2 item(s))

@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-site

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: seeded 11 dependency units (19.6 MiB) from HEAD's target dir in 0.0s
gate: reusing a run measured from the same merge-base binary
gate: reusing HEAD's own run, measured from binary 54273b0c2753bc0b
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_site::bench_highlight instructions 27784760.0 -> 27784760.0 (+0.0%)
ok    soothfast_site::bench_highlight callgrind_ir 27784760.0 -> 27784760.0 (+0.0%)
ok    soothfast_site::bench_highlight walltime_median_ns 1758978.0 -> 1758978.0 (+0.0%)
ok    soothfast_site::bench_highlight allocs 88069 -> 88069 (allowed <= 92472)
ok    soothfast_site::bench_highlight alloc_bytes 2079336 -> 2079336 (allowed <= 2183302)
ok    soothfast_site::bench_md_render instructions 31419478.0 -> 31419478.0 (+0.0%)
ok    soothfast_site::bench_md_render callgrind_ir 31419478.0 -> 31419478.0 (+0.0%)
ok    soothfast_site::bench_md_render walltime_median_ns 2506915.0 -> 2506915.0 (+0.0%)
ok    soothfast_site::bench_md_render allocs 68118 -> 68118 (allowed <= 71523)
ok    soothfast_site::bench_md_render alloc_bytes 3502526 -> 3502526 (allowed <= 3677652)
ok    soothfast_site::bench_highlight assert complexity: claimed O(n); growth drift x1.01 over sizes [128, 512, 2048] (limit x2.5)
ok    soothfast_site::bench_md_render assert complexity: claimed O(n); growth drift x1.00 over sizes [256, 1024, 4096] (limit x2.5)
gate: passed (2 item(s))

@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-sdk

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: seeded 18 dependency units (29.3 MiB) from HEAD's target dir in 0.1s
gate: bench binaries identical (code and data match) — no measurable change possible
gate: 2/2 items run code a stored measurement covers, measuring 0
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_sdk::bench_emit_typescript instructions 21061091.0 -> 21061091.0 (+0.0%)
ok    soothfast_sdk::bench_emit_typescript callgrind_ir 21061091.0 -> 21061091.0 (+0.0%)
ok    soothfast_sdk::bench_emit_typescript walltime_median_ns 1873860.0 -> 1873860.0 (+0.0%)
ok    soothfast_sdk::bench_emit_typescript allocs 42930 -> 42930 (allowed <= 45076)
ok    soothfast_sdk::bench_emit_typescript alloc_bytes 2938940 -> 2938940 (allowed <= 3085887)
ok    soothfast_sdk::bench_lower instructions 12228555.0 -> 12228555.0 (+0.0%)
ok    soothfast_sdk::bench_lower callgrind_ir 12228555.0 -> 12228555.0 (+0.0%)
ok    soothfast_sdk::bench_lower walltime_median_ns 1011570.0 -> 1011570.0 (+0.0%)
ok    soothfast_sdk::bench_lower allocs 23907 -> 23907 (allowed <= 25102)
ok    soothfast_sdk::bench_lower alloc_bytes 2064788 -> 2064788 (allowed <= 2168027)
ok    soothfast_sdk::bench_emit_typescript assert complexity: claimed O(n); growth drift x1.03 over sizes [16, 64, 256] (limit x2.5)
ok    soothfast_sdk::bench_lower assert complexity: claimed O(n); growth drift x1.10 over sizes [16, 64, 256] (limit x2.5)
gate: passed (2 item(s))

@soothfast-bot

soothfast-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

soothfast gate

soothfast-spec

gate: run cache keyed on callgrind (guest 80eb05cd5d172b67 glibc 2.43 341aa84b31e7d4e8 valgrind-3.26.0 method one-process)
gate: measuring merge-base of 2faafbaa9dc64e75c322a221d9172cf32501d026 in worktree (interleaved rounds)
gate: seeded 18 dependency units (29.3 MiB) from HEAD's target dir in 0.1s
gate: bench binaries identical (code and data match) — no measurable change possible
gate: 3/3 items run code a stored measurement covers, measuring 0
gate: gating backend = callgrind
gate: build=102e35 noise_floor=0.00% thresholds: instructions +5% ir +5% walltime +10.0% alloc/size +5% polls/wakes +5%
ok    soothfast_spec::bench_openapi_diff instructions 41741080.0 -> 41741080.0 (+0.0%)
ok    soothfast_spec::bench_openapi_diff callgrind_ir 41741080.0 -> 41741080.0 (+0.0%)
ok    soothfast_spec::bench_openapi_diff walltime_median_ns 4370430.0 -> 4370430.0 (+0.0%)
ok    soothfast_spec::bench_openapi_diff allocs 77722 -> 77722 (allowed <= 81608)
ok    soothfast_spec::bench_openapi_diff alloc_bytes 10815487 -> 10815487 (allowed <= 11356261)
ok    soothfast_spec::bench_openapi_document instructions 15564323.0 -> 15564323.0 (+0.0%)
ok    soothfast_spec::bench_openapi_document callgrind_ir 15564323.0 -> 15564323.0 (+0.0%)
ok    soothfast_spec::bench_openapi_document walltime_median_ns 1580405.0 -> 1580405.0 (+0.0%)
ok    soothfast_spec::bench_openapi_document allocs 30152 -> 30152 (allowed <= 31659)
ok    soothfast_spec::bench_openapi_document alloc_bytes 4715065 -> 4715065 (allowed <= 4950818)
ok    soothfast_spec::bench_serialize_yaml instructions 58721353.0 -> 58721353.0 (+0.0%)
ok    soothfast_spec::bench_serialize_yaml callgrind_ir 58721353.0 -> 58721353.0 (+0.0%)
ok    soothfast_spec::bench_serialize_yaml walltime_median_ns 5683815.0 -> 5683815.0 (+0.0%)
ok    soothfast_spec::bench_serialize_yaml allocs 74277 -> 74277 (allowed <= 77990)
ok    soothfast_spec::bench_serialize_yaml alloc_bytes 8533615 -> 8533615 (allowed <= 8960295)
ok    soothfast_spec::bench_openapi_diff assert complexity: claimed O(n); growth drift x1.02 over sizes [16, 64, 256] (limit x2.5)
ok    soothfast_spec::bench_openapi_document assert complexity: claimed O(n); growth drift x1.02 over sizes [16, 64, 256] (limit x2.5)
ok    soothfast_spec::bench_serialize_yaml assert complexity: claimed O(n); growth drift x1.00 over sizes [16, 64, 256] (limit x2.5)
gate: passed (3 item(s))

@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:04 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:10 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:10 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:29 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:29 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:33 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:35 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@soothfast-bot
soothfast-bot Bot deployed to soothfast-bot November 14, 2026 01:39 Active
@Verdenroz Verdenroz added soothfast:merge Merge once the required checks pass and removed soothfast:merge Merge once the required checks pass labels Nov 14, 2026
@soothfast-bot
soothfast-bot Bot merged commit 1eebfc4 into master Nov 14, 2026
20 checks passed

This branch was successfully deployed

1 active deployment
soothfast-bot — 4d1bdd2a Deployed Nov 14, 2026 by soothfast-bot[bot] via gate (soothfast-registry) / gate #1076
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

soothfast:merge Merge once the required checks pass soothfast:update Keep this branch up to date with the default branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Macro-generated items render as the macro call in the API surface

1 participant