fix(rust): scope-resolution coverage gaps — F66,F68,F71,F72 (#1934)#1974
Conversation
|
@prajapatisparsh is attempting to deploy a commit to the NexusCore Team on Vercel. A member of the Team first needs to authorize it. |
CI Report✅ All checks passed Pipeline Status
Test Results
✅ All 10940 tests passed 13 test(s) skipped — expand for details
Code CoverageTests
📋 View full run · Generated by CI |
magyargergo
left a comment
There was a problem hiding this comment.
PR Tri-Review — #1974 fix(rust): scope-resolution coverage gaps — F66,F68,F71,F72,F73 (#1934)
Verdict: not production-ready. Two of the five claimed gaps don't land as intended and one introduces a new false-edge class in the call graph. Branch hygiene: clean fork feature branch (no merge churn beyond a main merge). Merge state: BLOCKED on required review; CI: substantive jobs pending on the just-pushed head (Python/autofix/gitleaks/review pass; the Vercel fail is fork-auth, not a defect).
Methods & engines (read first). Genuine three-method review: Codex (gpt-5.5, the one independent engine — live; it reviewed via the GitHub connector since its local shell was unavailable) + GitNexus swarm + Compound-Engineering personas. Four Claude lanes returned full findings (correctness, adversarial, testing, plus the coordinator's own reproductions); the risk-architect and test/CI lanes ended mid-investigation, their domains covered by the others. Independence is asymmetric — most lanes are Claude under different prompts. Codex independently corroborated findings 2 and 3 below (strong); the headline (finding 1) is adversarial-only, so the coordinator reproduced its trigger + resolver path directly.
Headline (P1 — adversarial + coordinator-verified): macro invocations create false CALLS edges to same-named functions
The new F72 arms route macro_invocation through @reference.call.free with the macro's bare name. Rust macros and functions occupy disjoint namespaces, but the free-call resolver doesn't: a log!(…) invocation emits a free-call reference named log with arity=undefined; free-call-fallback.ts:167 resolves that name to a same-named fn log and :390 emits a CALLS edge (confidence ~0.85), and rustArityCompatibility returns unknown for undefined arity so no arity guard rejects it. Net: invoking log! produces a graph edge caller → fn log that the code never calls. The adversarial lane reproduced the materialized edge end-to-end via the full pipeline (caller → log same-file and run → assert cross-file); the coordinator independently reproduced the trigger (log!("hi") → @reference.call.free name="log" arity=undefined alongside fn log → @declaration.function) and code-read the resolver path. Before this PR, macros emitted no reference (clean miss), so this is a newly introduced false-positive class that degrades exactly the call-graph/impact-analysis accuracy GitNexus exists to provide. Blast radius: any Rust repo where an invoked macro name matches a free function name (common with macro_rules! helpers). Fix: tag macros distinctly (suffix !, or a dedicated @reference.macro) and do not route them through free-call CALLS resolution. [reproduced]
Inline findings
- [P1]
query.ts:132-133— macro→function falseCALLSedge (above).[reproduced] - [P2 · Codex + correctness + adversarial]
query.ts:53—let_declaration pattern: (identifier)→pattern: (_)(and the five@type-binding.*arms) makes@declaration.name/@type-binding.namecapture the whole pattern node text for any non-bare pattern:let (a, b)→ name"(a, b)",Some(val)→"Some(val)",Foo { field }→"Foo { field }",ref z→"ref z",n @ 1..=10→"n @ 1..=10"(coordinator-reproduced viaemitRustScopeCaptures). So F66/F68 is not actually delivered for destructuring/ref/captured patterns — the binding is registered under an unreferenceable name noa/b/val/field/zlookup can ever hit, and the same bogus name propagates to the type-binding arms. It's currently inert at the graph level (the legacy DAG still ownslet-binding nodes, so these don't materialize as symbols — verified) but pollutes the in-memory scope index and is baked into the golden + tests as "expected". It touches ~12 existing fixtures (golden captureGroups +1/+2). Fix: extract the inner identifier(s) (one binding per bound name) or restrict the arms to identifier-bearing shapes; don't capture whole-pattern text as a name.[reproduced] - [P2 · Codex + correctness + adversarial + testing]
query.ts:72— the F73(variadic_parameter pattern: (_))arm is dead (tree-sitter-rust'svariadic_parameter...has nopatternfield → 0 matches; verified), and thecaptures.ts:277arity change can't fire for real variadics (extern fns arefunction_signature_item, never thefunction_itemthe query captures). The F73 test (rust-coverage.test.ts:108,params.length >= 1) false-passes via the unrelatedfmtparameter, so deleting the dead arm wouldn't fail it. Fix: capture the variadic marker structurally and rewrite the test to assert something only the variadic produces (or drop the dead arm).[reproduced]
Lower-priority / body-only
- [P3] Scoped-macro arm is dead coverage (
query.ts:135-136):macro: (scoped_identifier)captures the full path (std::println/foo::bar) as the name, which resolves to nothing — so scoped macros aren't covered (and dodge the false-edge above only by accident). Untested.[reproduced by adversarial] - [P2 test-quality] Tests/golden bless the bogus names. The destructuring tests assert only
vars.length === 1(never the name); thelet ref xtest codifies@declaration.name === 'ref x'with a comment acknowledging it's the pattern text, not the variable; and the captures-golden hashes capture text into its digest, so"(a, b)"/"ref x"are locked in as the expected baseline. A reviewer can't see from the golden that wrong names were introduced.[code-read] - [P3]
captures.ts:277arity counts a...as one required+max parameter — semantically wrong for a variadic if it ever fired (it can't, for valid Rust).[code-read]
Validated / refuted (validation is a feature)
- F71 union (
@scope.class+@declaration.structname"MyUnion") and bare-identifier F72 macros (println/vec) work correctly — verified. The macro arms are written as separate specs (not a[…]alternation), correctly avoiding the tree-sitter-0.21 alternation-predicate hazard that bit prior PRs. - No symbol shadowing/collision from the bogus names — they contain
()/{}/@/spaces and can never collide with a valid Rust identifier (Codex + correctness + adversarial agree).let _ = xdoes not create a"_"binding (refuted). Two identicallet (a, b)don't collide on nodeId (refuted). The bogusletbindings are not materialized as graph nodes today (refuted graph corruption). The change is correctly Rust-provider-scoped (languages/rust/), honoring the no-language-names-in-shared-code rule.
Test gaps
- No test asserts a destructured identifier (
a/val/x) actually resolves — only capture counts. The F73 test proves nothing about the variadic arm. The scoped-macro arm and thecaptures.tsarity change have no real assertion. No regression test asserts the absence of the macro→function false edge.
Automated multi-tool digest (Codex gpt-5.5 + GitNexus swarm + Compound-Engineering personas). Verify before acting; the P1 macro-edge is adversarial-only + coordinator-reproduced, not independently cross-engine.
magyargergo
left a comment
There was a problem hiding this comment.
PR #1974 Tri-Review (local, not posted) — fix(rust): scope-resolution coverage gaps F66,F68,F71,F72,F73 (#1934)
Automated multi-method digest. Local-only — nothing posted to GitHub. Verify the cited
file:lineevidence before acting.
Method & engine breakdown
Three methods, with honest independence weighting:
- GitNexus swarm lanes (Claude) — risk, test/CI.
- Compound-Engineering personas (Claude) — correctness, adversarial, testing.
- Codex (the only independent engine) — LIVE this run (
gpt-5.5,xhigheffort; ran via the GitHub API because local shell was unavailable in its container). Coordinator-confirmed live: the run loggedcodex live: trueand returned 4 substantive, file:line-cited findings that reconcile cleanly with the Claude lanes (no inter-engine disagreement).
Weighting: findings where Codex + a Claude lane independently agree are STRONG; Claude-only agreement is "consistent across personas." The strongest single signal is end-to-end tsx reproduction of the capture-layer behavior (run read-only).
Process notes: The synthesis-critic gate was run; most of its "required corrections" were demands to conform to the gitnexus-pr-swarm-review 12-section template, which is a different skill's rubric — not adopted. Its substantive points were applied (F72 severity reconciled to P2; scoped-macro retagged [code-read]). One critic should-fix was itself wrong (CALLABLE_OR_TYPE_LIKE does exist — verified). Two earlier gitnexus-* lane runs truncated; their domains are covered by lanes that completed.
Scope reality-check (title vs. what actually lands)
The single production file is gitnexus/src/core/ingestion/languages/rust/query.ts (+19 lines of tree-sitter scope-query patterns).
| Claimed | Reality | Status |
|---|---|---|
| F66/F68 let-binding patterns | pattern:(identifier) correctly captures let x / let mut x, excludes destructuring |
✅ Lands correctly |
| F71 union | union_item tagged @declaration.struct → Struct node (not Union); pragmatic/benign, untested at pipeline layer |
|
| F72 macro | @reference.macro fires at the query layer but is dropped downstream → zero graph edges |
❌ Silent no-op |
| F73 variadic | Dropped in commit 93e4096f; no impl/test/fixture |
❌ Absent — title over-claims |
Net: the PR delivers less than the title states. F66/F68 are real; F71 is real but mislabeled & unverified end-to-end; F72 is inert; F73 does not exist.
Findings (severity order)
P2 (headline) — F72 macro coverage is a silent no-op · STRONG (Codex P1/0.99 + correctness + adversarial + risk) · [reproduced] + [code-read]
query.ts:127-132 emits @reference.macro, but it is discarded downstream:
scope-extractor.ts:990-991—const kind = referenceKindFromAnchor(anchor.name); if (kind === undefined) continue;scope-extractor.ts:1027-1049—referenceKindFromAnchorhas nomacrobranch (only call/read/write/type/inherits/import-use) → returnsundefined.gitnexus-shared/src/scope-resolution/reference-site.ts:34-40—ReferenceKindhas nomacromember.- No consumer of
@reference.macroexists anywhere insrc.
Reproduced (tsx): raw captures fire (['println','vec','log::info']) but every one is dropped at pass5CollectReferences → 0 ReferenceSites, 0 graph edges for any macro. Macro calls were invisible before this PR and remain invisible after.
Severity note: Codex rated this P1 (conf 0.99); I down-weight to P2 because it is not a runtime regression — nothing that worked breaks. It is the PR's most important issue because it silently fails to deliver a stated feature while a green test implies otherwise.
P2 — F72 test is capture-layer-only false confidence · STRONG (Codex + testing + risk) · [reproduced] + [code-read]
test/integration/resolvers/rust-coverage.test.ts:50-66 asserts only that @reference.macro appears in raw emitRustScopeCaptures output — never a ReferenceSite, graph edge, or usage node. It passes green because the capture layer fires, while the pipeline emits nothing. A reader of the test (titled "F72 — macro invocations") will believe macro resolution works.
P2 — Title and baselines.json over-claim F73 (variadic) · STRONG (Codex + risk) · [code-read]
F73 was explicitly dropped in commit 93e4096f ("drop variadic"); no impl/test/fixture remains. Yet the PR title still reads …F72,F73, and gitnexus/bench/scope-capture/baselines.json _note still says "…F72 macro, F73 variadic…". Audit-trail integrity problem (a future bisect for "when was F73 closed?" is misled). Fix: drop F73 from the title and the _note (or re-implement).
P2 — union_item → @declaration.struct: pragmatic/benign but untested & undocumented · STRONG-agree on mechanism · [reproduced] + [code-read]
query.ts:35-36 tags the union @declaration.struct → a Struct-labeled SymbolDefinition. This is deliberate and benign, not a defect:
scope-extractor.ts:703-714—normalizeNodeLabelsupports'union'→'Union', but the query never emits@declaration.union.node-lookup.ts:165-189(isLinkableLabel) lists Struct/Enum/Trait/… but excludesUnion;finalize-algorithm.ts:785-803(CALLABLE_OR_TYPE_LIKE) includes Struct, excludes Union;class-types.ts:4-7(ClassLikeNodeLabel) has no Union.- A
Union-labeled node would be an unresolvable orphan in every registry-primary gate. Struct is the more resolvable label.
Honest framing: the union literal genuinely is a constructor of the type, so the edge a Struct-labeled union yields is correct, not a false edge (correctness + adversarial both refuted the "bug" framing). The real cost is: (a) lost Union/Struct granularity, (b) no comment in query.ts explaining the deliberate downgrade, (c) no pipeline-level test that union.rs resolves to a Struct named MyUnion.
P2 — New test file is excluded from the scope-parity CI gate · consistent across Claude lanes (testing + risk) · [code-read]
.github/workflows/ci-scope-parity.yml runs test/integration/resolvers/<slug>.test.ts; gitnexus/scripts/run-parity.ts:44-45 resolves the Rust slug to rust.test.ts — not rust-coverage.test.ts. The new file runs only in the default vitest sweep, never under the legacy-vs-registry-primary parity gate. Combined with capture-layer-only assertions, F71/F72 get no pipeline-level CI coverage. The golden test catches query-layer drift but not the pipeline-level macro drop.
P3 — Scoped macro captures full path, not tail (latent, inert today) · STRONG (Codex + adversarial) · [code-read] (capture-layer reproduced)
query.ts:131-132 — macro:(scoped_identifier) @reference.name captures the whole path (log::info), whereas the scoped function-call pattern (query.ts:115-118) captures only the tail name:(identifier). Inert while @reference.macro is dropped, but a correctness bug the moment F72 is wired. Tag corrected to [code-read]: the capture text is reproduced, but the pipeline inconsistency is never observed (macro dropped). Fix: macro:(scoped_identifier path:(_) name:(identifier) @reference.name).
Validated / refuted (credit)
- VALIDATED
[reproduced]: F66/F68 let-pattern narrowing is clean —let x; let mut y; let (a,b); let Some(v); let Foo{field}; let ref r; let n @ 1..=10yields variable decls['x','y']only; no bogus"(a, b)". The explanatory query comment is a genuine quality touch. - VALIDATED
[reproduced]:(union_item) @scope.classdoes not over-capture sibling struct/enum bodies (3 separate Class scopes). - VALIDATED
[reproduced]:macro_rules!defs, attribute macros, and nested macros are not mis-captured. - REFUTED (not a defect): union-as-Struct is not a false-edge vector — the union literal is a real constructor; the edge is correct.
- No regression: new patterns fire only on
union/macro nodes; no existing capture renamed/reordered/removed; golden hash updated; no tree-sitter compile hazard (simple field captures, no alternation-predicate hazard); no O(n²) (dropped macro captures do no scope lookup).
Merge-risk verdict: MEDIUM
The lone production change is a pure tree-sitter query-string addition with no runtime logic change and a bounded blast radius (Rust scope extraction only). No working behavior regresses → not HIGH. Not LOW because of three compounding integrity issues (not a production regression): (1) F72 ships as a no-op with a false-confidence test; (2) F73 is claimed in the title + _note but absent; (3) F71 union-as-Struct is correct-but-undocumented with no pipeline test, and the new test file is outside the parity gate.
Recommended conditions before merge: (a) drop F73 from the title and baselines.json _note; (b) either wire F72 end-to-end (add 'macro' to ReferenceKind + a referenceKindFromAnchor branch + a consumer) or document it as capture-only and change the test to assert 0 ReferenceSites for macros; (c) add one pipeline-level assertion that union.rs resolves to a Struct named MyUnion, or document the deliberate Struct downgrade in query.ts; (d) fix the scoped-macro tail-capture (P3) before any F72 wiring; (e) ideally run rust-coverage.test.ts under the parity gate.
Suggested fixes (checklist)
Ordered by priority. Anchors map to the inline comments in pr-1974-review-payload.json.
- Drop F73 from the PR title +
baselines.json_note(or re-implement it) — fastest integrity fix, zero code risk. (C3 · baselines.json:33) - Resolve the F72 no-op — either (a) wire macros end-to-end: add
'macro'toReferenceKind(reference-site.ts:34-40), add acaseinreferenceKindFromAnchor(scope-extractor.ts:1027-1049), and a consumer that emits the edge; or (b) keep it capture-only: document the intent inquery.ts+reference-site.tsand change the test to assert 0 ReferenceSites for macros. (C1 · query.ts:129) - Fix the F72 test altitude — assert resolved
ReferenceSites/edges (not just raw captures), matching whichever path above is chosen. (C2 · rust-coverage.test.ts:54) - Wire
rust-coverage.test.tsinto the scope-parity gate (or add an equivalent case torust.test.ts) so F71/F72 get legacy-vs-registry-primary CI coverage. (C2) - Document + test the union→Struct choice — a one-line rationale comment at
query.ts:36, plus a pipeline-level assertion thatunion.rsresolves to aStructnamedMyUnion. (C4 · query.ts:36) - Fix the scoped-macro tail capture before any F72 wiring:
macro:(scoped_identifier path:(_) name:(identifier) @reference.name). (C5 · query.ts:132) - (nice-to-have) Add negative assertions for the 5 destructuring
letshapes inpatterns.rs(pin thepattern:(identifier)intent against a futurepattern:(_)regression), and amacro_rules!-definition + invocation fixture.
CI / branch / visibility
- CI (at review time): PASS — lint, typecheck, typecheck-web, tree-sitter-ABI, autofix, gitleaks. PENDING — scope-parity, tests. Vercel "fail" = deploy-auth gate, not a test failure. Note: scope-parity runs
rust.test.ts, so a green parity run does not coverrust-coverage.test.ts. - Merge state:
BLOCKED/MERGEABLE— blocked on pending required checks, no conflicts. - Branch hygiene: two
Merge branch 'main'commits (622053ae,03dac44f) present but harmless/merge-safe; no unrelated churn; single-domain (Rust query). - Could verify: all cited
file:lineevidence (re-read), the tsx reproductions, the legacy/gate wiring, Codex liveness. Couldn't verify: pending CI results; fullnpx gitnexus analyzeend-to-end graph output (worktrees can't build — validated via tsx/extract-level instead).
Automated three-method digest (2 Claude method-families + live Codex). High-signal starting point, not a final verdict — verify cited evidence and reproductions before acting.
|
|
||
| ;; References — macro invocations (disjoint namespace from functions) | ||
| (macro_invocation | ||
| macro: (identifier) @reference.name) @reference.macro |
There was a problem hiding this comment.
[P2 · headline] F72 macro coverage is a silent no-op. This @reference.macro capture fires at the query layer, but the scope-extractor drops it: referenceKindFromAnchor (scope-extractor.ts:1027-1049) has no macro case so it returns undefined, and pass5CollectReferences (scope-extractor.ts:990-991) does if (kind === undefined) continue;. ReferenceKind (gitnexus-shared/src/scope-resolution/reference-site.ts:34-40) has no macro member, and nothing in src consumes @reference.macro. Net: 0 ReferenceSites / 0 graph edges for any macro invocation — macros are as invisible after this PR as before. Not a regression, but F72 ships inert.
Fix: add 'macro' to ReferenceKind + a referenceKindFromAnchor branch + a consumer, or document it as capture-only and drop the F72 claim from the title.
[reproduced via tsx + code-read; corroborated by Codex (gpt-5.5/xhigh) + correctness/adversarial/risk lanes]
There was a problem hiding this comment.
Resolved by fully wiring F72. Added a 'macro' ReferenceKind + a MacroRegistry: referenceKindFromAnchor now maps @reference.macro → 'macro', resolve-references routes those sites through the macro registry, the edge mappers map 'macro' → USES, and isLinkableLabel makes Macro linkable so the registry def bridges to the legacy @definition.macro graph node. Net: println!() / vec![] / log::info!() now produce real USES edges to their Macro defs. (49d2940)
| it('macro_invocation with bare identifier emits @reference.macro', () => { | ||
| const src = `fn f() { println!("hi"); }\n`; | ||
| const matches = emitRustScopeCaptures(src, 'test.rs') as CaptureMatch[]; | ||
| const macroRefs = matches.filter((m) => m['@reference.macro']); |
There was a problem hiding this comment.
[P2] Capture-layer-only assertion → false confidence. This asserts only that @reference.macro appears in the raw emitRustScopeCaptures output — never a ReferenceSite, graph edge, or usage node. Because the capture is dropped downstream (see the query.ts macro note), this test passes green while F72 produces nothing in the graph.
Also: this file is not run by the scope-parity CI gate — ci-scope-parity.yml → run-parity.ts:44-45 resolves the Rust slug to rust.test.ts, not rust-coverage.test.ts, so F71/F72 get no pipeline-level CI coverage.
Fix: assert resolved ReferenceSites/edges (or, if macros stay capture-only, assert 0 ReferenceSites for them), and wire this file into the parity gate.
[reproduced; Codex + testing/risk lanes]
There was a problem hiding this comment.
Addressed. Pipeline-level resolution is now asserted in rust.test.ts (the parity-gated file): the macro resolves to a USES edge on the Macro, with no false CALLS. Macro resolution is registry-primary-only, so the two resolution assertions are listed in LEGACY_RESOLVER_PARITY_EXPECTED_FAILURES['rust'] and skipped under the legacy half (the node-materialization assertion runs on both). The capture-layer tests here are reframed as capture-only and now also pin the scoped-macro tail + the macro_rules! declaration capture. (49d2940)
| "scaling_budget": 1.5, | ||
| "_rebaselined": "#1956 tri-review U1: rust-qualified-trait fixture (scoped + generic-of-scoped impl trait paths); bareTypeIdentifier now resolves scoped_type_identifier bases by their name: tail (additive, no existing-fixture drift); linear (~1.04)." | ||
| "_rebaselined": "#1956 tri-review U1: rust-qualified-trait fixture (scoped + generic-of-scoped impl trait paths); bareTypeIdentifier now resolves scoped_type_identifier bases by their name: tail (additive, no existing-fixture drift); linear (~1.04).", | ||
| "_note": "PR #1934: F66/F68 pattern wildcards, F71 union, F72 macro, F73 variadic — fixture count 117→124, fingerprint drift expected." |
There was a problem hiding this comment.
[P2] F73 is over-claimed. This _note (and the PR title) lists F73 variadic, but F73 was dropped in commit 93e4096f ("drop variadic") — no implementation, test, or fixture remains. A future bisect tracing "when was F73 closed?" will be misled.
Fix: remove F73 variadic from this note and from the PR title (or re-implement F73).
[code-read; Codex + risk lane]
|
|
||
| ;; Declarations — union | ||
| (union_item | ||
| name: (type_identifier) @declaration.name) @declaration.struct |
There was a problem hiding this comment.
[P2] Union is labeled Struct, not Union — intentional/benign, but undocumented & untested. @declaration.struct yields normalizeNodeLabel('struct')='Struct'. This is actually the correct pragmatic choice: every registry-primary resolution gate — isLinkableLabel (node-lookup.ts:165-189), CALLABLE_OR_TYPE_LIKE (finalize-algorithm.ts:785-803), ClassLikeNodeLabel (class-types.ts:4-7) — includes Struct but excludes Union, so a @declaration.union node would be an unresolvable orphan. So this is not a bug. But (a) no comment explains the deliberate downgrade, and (b) no pipeline-level test asserts union.rs resolves to a Struct named MyUnion.
Fix: add a one-line rationale comment here, plus a pipeline-level union-resolution test.
[reproduced + code-read; Codex + correctness/adversarial]
There was a problem hiding this comment.
Addressed, and it went deeper than docs: the union had no graph node at all — the legacy RUST_QUERIES never captured union_item, so the @declaration.struct scope capture had nothing to resolve to. Added (union_item name: (type_identifier) @name) @definition.struct to materialize it, plus the rationale comment (Struct chosen because every registry gate includes Struct, excludes Union). New pipeline test rust.test.ts › Rust union resolution asserts union.rs resolves to a Struct named MyUnion and that MyUnion { .. } emits a CALLS edge to it — runs on both parity halves. (49d2940)
| macro: (identifier) @reference.name) @reference.macro | ||
|
|
||
| (macro_invocation | ||
| macro: (scoped_identifier) @reference.name) @reference.macro |
There was a problem hiding this comment.
[P3 · latent] Scoped macro captures the full path, not the tail. macro:(scoped_identifier) @reference.name captures e.g. log::info, whereas the scoped function-call pattern (lines 115-118) captures only the tail name:(identifier). Inert today (the macro capture is dropped — see above), but a correctness bug the moment F72 is wired up.
Fix: macro:(scoped_identifier path:(_) name:(identifier) @reference.name).
[code-read; Codex + adversarial]
There was a problem hiding this comment.
Fixed. The scoped macro arm now captures the tail identifier: macro: (scoped_identifier name: (identifier) @reference.name), mirroring the scoped free-call pattern — log::info! resolves as info, not log::info. Capture-layer regression added in rust-coverage.test.ts. (49d2940)
|
@prajapatisparsh don't worry I'm looking into this |
# Conflicts: # gitnexus/bench/scope-capture/baselines.json
I just saw this , I was sleeping 🫠 |
Yes, there's a tricky path I need to debug for myself. Thanks for this contribution! 👏 |
…igyanpatwari#1974 review) Addresses the outstanding abhigyanpatwari#1974 review (second batch). Per maintainer decision, F72 is FULLY WIRED rather than documented capture-only. F72 macro — was a capture-only no-op (@reference.macro dropped downstream): - gitnexus-shared: add 'macro' ReferenceKind + Reference.kind; add MACRO_KINDS (['Macro']) and a MacroRegistry that resolves a macro invocation ONLY to a macro_rules! definition — never a same-named free function (the disjoint-namespace guarantee the review required). - scope-extractor: referenceKindFromAnchor @reference.macro -> 'macro'; normalizeNodeLabel 'macro' -> Macro. - resolve-references: route 'macro' sites through MacroRegistry. - emit-references / graph-bridge edges: 'macro' -> USES (kept out of the CALLS keyspace, which denotes function/method dispatch). - node-lookup isLinkableLabel: Macro is linkable, bridging the registry def to the legacy @definition.macro graph node. - rust query: capture macro_rules! as @declaration.macro; fix the scoped macro arm to capture the tail identifier, not the full path (P3). F71 union — the @declaration.struct scope capture had no graph node to resolve to (legacy RUST_QUERIES never captured union_item): - legacy query: capture union_item as @Definition.struct so the union is materialized as a Struct node and is genuinely resolvable. - query.ts: document the deliberate union->Struct downgrade rationale. Tests: - rust.test.ts (parity-gated): pipeline-level union resolution + macro resolution (USES to the Macro, exactly one CALLS to fn, none to Macro). Macro resolution is registry-primary-only -> listed in LEGACY_RESOLVER_PARITY_EXPECTED_FAILURES['rust']. - rust-coverage.test.ts: scoped-macro tail + macro-def capture assertions; reframed as capture-layer only, pointing at the pipeline tests. - new fixtures rust-macro, rust-union. F73: dropped from baselines.json _note (variadic was never implemented). Rebaselined the rust capture golden + scope-capture fingerprint (a5fdff2c..., scaling ~0.99, fixture_count 126). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✨ PR AutofixFound fixable formatting / unused-import issues across 20 changed lines. Comment |
…i#1974) CI quality/format gate — collapse the multi-line 'macro' addition back to one line (fits the 100-col print width). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings main (78ad6bc) — #1934 rust F71 union / F72 macro, rust-coverage (#1974), Go interface-impl/type-binding work, hook-resolver changes — into the #1981+#1982 branch (cpp/ruby qualified nested-type identity + resolution-side same-tail fix). Conflicts resolved (2): - test/integration/resolvers/rust.test.ts: kept BOTH the #1981 deferred Rust same-tail `describe.skip` block AND main's F71 (union) / F72 (macro) describe blocks — independent additions at the same location. - bench/scope-capture/baselines.json: rust fingerprint recomputed for the MERGED corpus (main's rust-coverage/F71/F72 fixtures UNION #1981's rust-nested-tail-collision, 126→127 fixtures) → 56ffc1c0…; cpp/ruby auto-merged (the #1982 fingerprints intact). All other entries (reference-site.ts, scope-extractor.ts, helpers.ts, rust golden) auto-merged cleanly. Verified post-merge: tsc clean; bench 14/14 PASS; rust.test.ts 169 pass / 1 skip; cpp 278 + ruby 142 + 7 capture goldens (479) all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes the #1934 Rust scope-resolution coverage gaps.
F66/F68 — let-binding patterns:
let_declarationcapturespattern:(identifier)(coverslet x/let mut x); destructuring shapes are intentionally excluded — capturing(_)would register an unreferenceable whole-pattern name ("(a, b)").F71 — unions:
union_itemis materialized as a Struct-labeled node and is resolvable (the union literal is a real constructor). Every registry-primary resolution gate includesStructbut excludesUnion, soStructis the resolvable + honest label; rationale documented inline. Also added the missingunion_itemarm to the legacyRUST_QUERIESso the node actually exists.F72 — macros (fully wired):
macro_rules!definitions are captured (@declaration.macro→Macro) and macro invocations (@reference.macro) resolve via a dedicated MacroRegistry (acceptedKinds: ['Macro']) to the macro definition, emitting a USES edge to theMacronode. Because the registry only acceptsMacrodefs, a macro invocation can never bind to a same-named free function — macros and functions stay disjoint namespaces (the false-CALLS-edge class flagged in review). Scoped macro invocations capture the tail identifier (log::info!→info).F73 — dropped (variadic was never implemented; removed from the title + baselines note).
Tests: parity-gated pipeline-level union + macro resolution in
rust.test.ts; capture-layer regressions inrust-coverage.test.ts; newrust-macro/rust-unionfixtures. Rust capture golden + scope-capture fingerprint rebaselined (~0.99 linear).F67/F69/F74 already closed by #1937/#1940/#1956.
Maintainer follow-up (review of #1974): merged latest
main, rebaselined, and addressed the review threads — fully wiring F72 per the review's option (a).