Plan: Add the whitaker_support_macros proc-macro crate (1.3.1) - #352
Plan: Add the whitaker_support_macros proc-macro crate (1.3.1)#352leynos wants to merge 3 commits into
Conversation
|
Warning Your free Security trial is over. An organization admin can activate billing to continue. |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Update: D-9 accepted as option (b); R-1 discharged by spikePlan status is now ADR 002 amendments
R-1 discharged:
|
Draft the execution plan for roadmap item 1.3.1: the `crates/whitaker_support_macros` proc-macro crate implementing `#[dylint_expect(lib = ..., lints(...), reason = ...)]` per ADR 002. The plan decomposes the work so the one genuinely general property -- argument-key well-formedness and order-independence -- lands on a pure function over a three-symbol alphabet, provable in Verus and exhaustively enumerable in a test, while token-tree behaviour is covered by parameterized, snapshot, property, and trybuild fixtures. Scope was extended by user direction to include crates.io publish wiring, the ADR 002 status change to Accepted, and a Dylint suite design cross-reference. An opening prototyping milestone answers the empirical questions the design rests on -- notably whether `#[expect(...)]` works at all for Dylint-registered lints -- before any production code is written.
Run the prototyping milestone during planning rather than deferring it, and record what it found. ADR 002's mandated expansion does not suppress `unexpected_cfgs`: that diagnostic resolves during cfg-expansion, before the annotated item's own lint levels are in scope, so a sibling `#[allow]` arrives too late. Verified end-to-end with a real proc macro emitting the ADR's exact four attributes. Two of the remaining three mandated attributes suppress diagnostics the gated form never emits, and the third removes the only signal that catches a misspelt lint name. Record the deviation as D-9 with three options and a recommendation, and set the plan to BLOCKED pending explicit acceptance. Fold in a six-lens design review. Cut the Verus sidecar, the permutation property, the BDD feature file, and two new assertion crates: the argument-key alphabet has three symbols, so by pigeonhole the 121-case enumeration is a total decision procedure and the proof would have restated a decidable property. Flatten the module layout after a misread of `self_named_module_files`; rename `grammar` to `keys` because it never covered arity; carry position in `ArgShapeError` so diagnostics can be anchored; hold `LitStr` in the newtypes so spans survive and the library name gains a real invariant; drop `syn`'s `full` feature before it leaks to downstream consumers; publish the new crate last and guard the block; correct the non-existent `whitaker_lints` library name throughout; replace INV-DIAG-1's non-vacuity control, which was itself vacuous.
Amend ADR 002 per the accepted deviation D-9(b) and move it to Accepted. The macro expands to the `cfg_attr` gate alone; the `check-cfg` manifest entry is documented as the mechanism rather than a convenience, because a sibling `#[allow(unexpected_cfgs)]` provably cannot suppress a diagnostic resolved during cfg-expansion. Correct Option D's rejection rationale, which rested on two false premises: the gated form emits neither `unknown_lints` nor `clippy::allow_attributes`. Correct two rows of Table 1 accordingly -- "works in downstream crates without extra config" was the decisive argument for Option C over Option D and is in fact Low for every option. Replace the non-existent `whitaker_lints` library name with `whitaker_suite`. Discharge R-1 with a spike, since discarded. `#[expect(...)]` does work for Dylint-registered Whitaker lints: against an individual lint library built from current source, item-level allow, item-level expect, module-level allow and the gated expect all suppress correctly with no spurious unfulfilled-expectation warnings. Record R-1b, which the spike surfaced. The aggregated `whitaker_suite` library ignores lint-level attributes entirely and emits a spurious `unfulfilled_lint_expectations` warning for every expect, while individual libraries built from the same commit behave correctly. Staleness, lint-identity mismatch and cfg_attr interaction were each ruled out by controlled comparison. Since the suite is what every installed consumer loads, no attribute-based suppression works in practice today. This gates ADR 002 migration phase 3, not 1.3.1 delivery, whose obligations are all token-level. Move the plan to APPROVED.
fcbe353 to
114e6bf
Compare
Summary
ExecPlan for roadmap item 1.3.1 — the
crates/whitaker_support_macrosproc-macro crate implementing#[dylint_expect(lib, lints, reason)]per ADR 002.📄 Plan:
docs/execplans/1-3-1-add-whitaker-support-macros-proc-macro-crate.mdStatus:
BLOCKED. The plan's prototyping milestone was run during planning rather than deferred, and it falsified a premise of ADR 002. A proposed architecture deviation (D-9) is recorded with three options and a recommendation; no implementation may begin until one is accepted.What the prototype found
ADR 002's mandated four-attribute expansion does not suppress
unexpected_cfgs. That diagnostic is resolved during cfg-expansion, before the annotated item's own lint levels are in scope, so a sibling#[allow(unexpected_cfgs)]arrives too late. An attribute macro cannot place theallowin an enclosing scope without wrapping the item and changing its semantics.Verified end-to-end with a real
proc-macro = truecrate emitting the ADR's exact attributes, consumed by a crate carrying this workspace's lint policy — it still warns at the call-site.cfg_attrgate, noallowsunexpected_cfgscheck-cfg = ['cfg(dylint_lib, values(any()))']allow(unexpected_cfgs)on enclosing module / as inner attributeunknown_lintsfires — the typo safety netTwo of the remaining three mandated attributes suppress diagnostics the gated form never emits. The third,
allow(unknown_lints), removes the only signal that catches a misspelt lint name — turning every typo into a silent no-op. ADR 002 §Options considered rejects Option D partly on these grounds, so that rationale needs correcting too.Decision required (D-9)
cfg_attrgate alone, Whitaker adds onecheck-cfgentry and documents it as the consumer prerequisite. Preserves typo detection.dylint_expect_shapelint that validates call-sites against loaded libraries and registered lint names — closing all three silent-no-op routes no macro can. Removes 1.3.1–1.3.4 as written.The plan is written for (b) and ready to execute on acceptance.
Design review
A six-lens expert panel reviewed the first draft. Resulting changes:
googletest/pretty_assertions. The argument-key alphabet has three symbols, so by pigeonhole the 121-case enumeration is a total decision procedure — the proof would have restated a decidable property, whichAGENTS.mdforbids.make verusalso runs in no CI workflow, and no proof file inverus/has ever been modified.clippy::self_named_module_files; renamedgrammartokeys, which is all it ever validated.ArgShapeErrorto carry position so diagnostics can be anchored; newtypes now holdLitStrso spans survive andLibraryNamegains a real invariant.syn'sfullfeature before it leaks into the published manifest and onto every downstream build graph.whitaker-installerin an all-or-nothingset -euxo pipefailblock.whitaker_lintsthroughout — no such library exists; the real names arewhitaker_suiteand the per-lint crates..stderrfiles always differ).Follow-up work identified
dylint_expect_shapelint (proposed 1.3.5) — the only mechanism that can close the wrong-liband misspelt-lint silent no-ops.crates/whitaker_test_macrosemits#[cfg_attr(clippy, expect(clippy::allow_attributes, ...))], which the current toolchain rejects withclippy::unnecessary_clippy_cfg.Verification
make markdownlintandmake nixiepass. No code changes in this PR.References
🤖 Generated with Claude Code
Summary by Sourcery
Approve and document the revised plan for adding conditional Dylint expectation macros after validating the original expansion and identifying remaining integration risks.
Enhancements:
whitaker_support_macrosproc-macro, reducing the expansion to a cfg-gated Dylint expectation and requiring a consumercheck-cfgentry.Documentation: