Skip to content

Code Analysis Go Rust Investigation Batch

Tu Shaokun edited this page Nov 8, 2026 · 16 revisions

Go/Rust real-change investigation batch (2026-11-08)

Draft, not merged: #1290, head c54b0f04dca8e1f52a158a6cde2ddcd10c1d2866, base codex/go-rust-batch-baseline (70bdf0227, merge of Go #1285 and Rust #1288). Review order: #1289 merges both baselines; this PR targets that merged branch. No merge, no labs/code-analysis update, no live installation.

Question

On real Go and Rust changes, does the normal change query answer four things: which definition changed, who directly calls it, which calls only prove an interface/trait declaration, and where can the reader verify the call in source?

Fixed baselines

Line Commit Meaning
Go 209f4857c #1285 accepted interface-candidate work
Rust fef42b806 #1288 fixed commit
Batch base 70bdf0227 merge of both lines; this branch reuses it instead of duplicating history

Sample trees are independent git worktree checkouts at the fixed base/head commits. No project build or test was executed. Go used Go 1.27.2, default GOOS/GOARCH, cgo disabled. clap and tracing were read with a generated Cargo.lock because the extractor uses --locked.

Cases

Four previously unused repositories: caddyserver/certmagic, gin-gonic/gin, clap-rs/clap, tokio-rs/tracing. marshallpierce/rust-base64 is regression only.

Case Lang Definition Result
certmagic-store Go *FileStorage.Store 3 direct + 9 interface candidates, all correct
certmagic-load Go *FileStorage.Load 20/20 correct (2 determined, 18 interface)
certmagic-interface Go Storage.Store 5/5 interface references + *FileStorage.Store
certmagic-interface-load Go Storage.Load reserved, 13/13 + *FileStorage.Load
gin-close / gin-hijack Go CloseNotify / Hijack documented gap: external embedded interfaces
clap-any / clap-typed Rust parse_ref_ defaults documented gap: calls inside ok!(...)
tracing-subscriber Rust Subscriber::event_enabled 1/5; dispatcher.rs:514 now correct
tracing-layer Rust Layer::event_enabled documented gap: renamed generic field
base64-inner-decode Rust GeneralPurpose::internal_decode 4/4 regression

Reserved answers were committed in cca4e8066 before any candidate run and executed only after the rules were final. They caused no rule change.

Whole-batch result

Scope Definitions Calls found Wrong Missed
All 11 cases 11/11 55/72 0 17
Go (6) 6/6 50/55 0 5
Rust (5) 5/5 5/17 0 12
Reserved (2) 2/2 13/14 0 1

Target mix: 5 determined, 62 candidate (interface/trait declaration), 5 explicitly unknown. Every candidate carries runtimeTarget: "not-determined"; none is presented as a definite implementation.

Product fixes

  1. Trait-default references. Default bodies are registered at the fn keyword while trait calls target the method name. The change question unions both anchors. Trigger: tracing-core/src/dispatcher.rs:514 resolves to subscriber.rs:305:8, direct caller event at line 513. Negative control: a concrete impl call stays resolved to the impl.
  2. Field receivers. Named struct field hints plus impl self types resolve self.<field> and as_ref/deref/borrow to a trait bound or a unique nominal impl. Trigger fixture produces rust-trait-method-candidate for a generic field and rust-trait-impl for a concrete field; the concrete call must not become a trait candidate.

Before/after on the affected Rust questions: baseline 0/12, after 5/16, 0 wrong targets.

Independent review

A read-only reviewer reproduced three defects in the first cut, all fixed in c54b0f04d:

  • Module paths are crate-local, so a same-named trait in another workspace member shared the qualname and its callers were attached to the changed default body. The anchor union is now restricted to the declaring file.
  • A generic field hint was consumed with the impl's own bounds even when the impl instantiated the struct with another type (impl<T: Gate> Holder<u8>). It now fails closed unless the self type carries the same parameter; the same-named local-struct fallback was removed.
  • self.as_ref()/deref()/borrow() is a method call, so the original branch never ran. It now handles ExprMethodCall; the dead self::as_ref branch was removed.

Regression coverage: a two-crate workspace fixture that discriminates the cross-crate case, a different-instantiation negative control, and an as_ref positive control. The full batch is unchanged at 55/72 with 0 wrong targets.

Reproduction

node archify/bin/archify.mjs code-analysis task \
  --question "Which callers reach it?" \
  --base-root samples/<case>-base --root samples/<case>-head \
  --entry <file> --format json --out /tmp/query.json

python3 benchmarks/code-analysis-go-rust-investigation-batch-20261108/run.py \
  --cli archify/bin/archify.mjs --samples samples \
  --out benchmarks/code-analysis-go-rust-investigation-batch-20261108/evidence/final \
  --include-reserved

The committed evidence/final/summary.json and evidence/reserved/summary.json are authoritative; full query JSON is regenerated locally by the runner (up to ~1 MB per paired question) and is not committed.

Verification

  • node --test modules/code-analysis/test/*.test.mjs: 432 pass, 0 fail, 0 skipped.
  • archify.zip SHA256 0776f4264d29d8b886c1c7d3238fa776306afb80a03524abcd62cc925b88c0d5, rebuilt with official Node 22 (zlib 1.3.1-e00f703) and byte-identical on a second build.
  • Unpacked ZIP replayed certmagic-store (3 direct, 9 interface) and tracing-subscriber (1 reference, caller event) with the same results as source. The unpacked module dependencies were installed with npm install --omit=dev before replay.
  • CI run 42491022941 for head eaa06802a.

Limits and next problem

Remaining misses are macro-argument calls (clap), external embedded interface implementations (gin), and field receivers whose generic name changes between struct and impl, plus macro-produced receivers (tracing layered.rs, fmt/mod.rs).

The most worthwhile next problem is substitution through renamed generics: Layered<L, I, S = I> stores inner: I, while the impl is impl<S> Subscriber for Layered<L, S>. Mapping impl parameters to struct parameters at the type-hint layer would recover several currently missed calls without a broader receiver heuristic.

Attribution

Benchmark design, scoring, extractor/query changes and tests were written in this session on top of the team baselines. Upstream repositories and commits are the work of their maintainers.

Clone this wiki locally