scan: macro_rules regions read as blindspots and fail --strict #35

Closed
opened 2026-07-16 07:51:44 +00:00 by PerishFire · 0 comments
Owner

What happened

v0.3.0 cannot parse macro_rules! bodies or item-position bang-macro
invocations. Each such region reports blindspot unparsed region, and
--strict exits nonzero on any blindspot — so a repo that ships a
declarative macro cannot pass its guard.

Hit in keel (PerishLab/keel #48): keel-gate ships its resource
definitions through a declarative macro, per settled product law:

  • crates/gate/src/make.rs — the macro_rules! gate { ... } body
    (expands to #[resource] structs bound to the caller's identity unit)
  • crates/api/src/bin/forge/gear.rs — the call site keel_gate::gate!(Actor);
crates/gate/src/lib.rs:14:1 blindspot unparsed region
crates/gate/src/lib.rs:38:5 blindspot unparsed region
crates/api/src/bin/forge.rs:32:1 blindspot unparsed region
0 faults, 3 blindspots, 110 debts

Workaround in place (debt)

Macros were isolated into dedicated files (make.rs, gear.rs) and those
two files are excluded in negentropy.toml. That removes real code from
law coverage and is recorded as debt in keel's vocabulary — to be
unexcluded once the scanner learns macros.

What would resolve it

Either (in preference order):

  1. Parse macro_rules! bodies as token trees and scan the expansion-
    shaped
    content it can recognize (idents/blocks), applying word and
    depth laws where parseable — blindspot only what is truly opaque.
  2. Treat macro_rules! items and item-position path::bang!(...)
    invocations as declared blindspots that do not fail --strict
    (a distinct class from unexpected parse failures), optionally gated
    by an explicit [scan] macros = "allow" seat in negentropy.toml.
  3. An inline allow pragma with a narrower radius than file-level exclude.

Option 2 keeps strictness honest: an unparsed region the author named
is a different signal from one the scanner stumbled on.

Repro

Any crate with an exported macro_rules! + one invocation; run
negentropy --strict . with v0.3.0.

## What happened v0.3.0 cannot parse `macro_rules!` bodies or item-position bang-macro invocations. Each such region reports `blindspot unparsed region`, and `--strict` exits nonzero on any blindspot — so a repo that ships a declarative macro cannot pass its guard. Hit in keel (PerishLab/keel #48): `keel-gate` ships its resource definitions through a declarative macro, per settled product law: - `crates/gate/src/make.rs` — the `macro_rules! gate { ... }` body (expands to `#[resource]` structs bound to the caller's identity unit) - `crates/api/src/bin/forge/gear.rs` — the call site `keel_gate::gate!(Actor);` ``` crates/gate/src/lib.rs:14:1 blindspot unparsed region crates/gate/src/lib.rs:38:5 blindspot unparsed region crates/api/src/bin/forge.rs:32:1 blindspot unparsed region 0 faults, 3 blindspots, 110 debts ``` ## Workaround in place (debt) Macros were isolated into dedicated files (`make.rs`, `gear.rs`) and those two files are excluded in `negentropy.toml`. That removes real code from law coverage and is recorded as debt in keel's vocabulary — to be unexcluded once the scanner learns macros. ## What would resolve it Either (in preference order): 1. Parse `macro_rules!` bodies as token trees and scan the *expansion- shaped* content it can recognize (idents/blocks), applying word and depth laws where parseable — blindspot only what is truly opaque. 2. Treat `macro_rules!` items and item-position `path::bang!(...)` invocations as *declared* blindspots that do not fail `--strict` (a distinct class from unexpected parse failures), optionally gated by an explicit `[scan] macros = "allow"` seat in negentropy.toml. 3. An inline allow pragma with a narrower radius than file-level exclude. Option 2 keeps strictness honest: an unparsed region the author *named* is a different signal from one the scanner stumbled on. ## Repro Any crate with an exported `macro_rules!` + one invocation; run `negentropy --strict .` with v0.3.0.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
PerishFire/negentropy#35
No description provided.