Skip to content

fix: say what an answer could not see; bind Rust paths and same-line calls - #34

Merged
maxgfr merged 2 commits into
mainfrom
fix-eval-findings
Oct 12, 2026
Merged

maxgfr merged 2 commits into
mainfrom
fix-eval-findings

Conversation

@maxgfr

@maxgfr maxgfr commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Why

After 2.31.6 shipped, codeindex ran against five large real repositories (vite, TypeScript's Go port at 67k files, django, terraform, ripgrep), with the answers judged as a coding agent would use them. Nothing crashed. Five answers looked complete but were not, and two queries were about 20% slower than 2.31.5 on the largest repository. All of these also existed in 2.31.5 except the slowdown.

Fixes

Before After
vite callers resolveConfig: 56 of 68 sites. terraform NewContext: 53 of 78. The 512-site per-file cap cut test files without saying so. 68/68 and 78/78. The cap is now 8192, which makes the TypeScript index 1% larger and no slower. A file the cap still cuts carries callsCapped, and callers and refs name it in a new coverage field.
TypeScript refs NewChecker → {defs: []}, exit 0. outline checker.go → "no such file". The file is 1.4 MB, over --max-bytes. coverage.notIndexed names checker.go and the --max-bytes value that would index it. outline, symbol-at and complexity give the reason. find writes it to stderr. CLI and MCP behave the same.
ripgrep callers search_parallel missed crate::search_parallel(...). crate:: and super:: bind to the crate root or the parent module, private items included. An inline mod tests and a Cargo target file (src/bin/x.rs, examples/, tests/, benches/) are handled.
ripgrep callers main.rs#search reported the mod search; declaration. A call never binds to a mod, module, package or namespace declaration.
incremental.NewProgram(compiler.NewProgram()) kept one of its two calls. Call sites are deduplicated by name, line and receiver on both tiers. A caller line appears once when both calls reach the same declaration.

Performance

On the TypeScript repository, search is back to 2.31.5's time (2.0–2.2 s against 2.0–2.3 s). Two changes, both with identical output:

  • subtokens uses ASCII character classes for ASCII text. An equivalence test checks the result against the Unicode spelling.
  • The self-index guard compares one precomputed prefix. It used to call path.relative for every file.

repomap is within noise. deadcode takes the same time and uses 3–7% more memory, down from 20%.

Validation

pnpm typecheck, pnpm test (2,216 tests), pnpm check:build, pnpm test:e2e (98) and pnpm quality:report pass, and the report is unchanged. The e2e command matrix passed on ripgrep, gin, pinia, plug and code-du-travail-numerique (300 checks). An independent audit of the first commit found the two Rust path cases (inline mod, Cargo targets), which the second commit fixes, each with a test.

EXTRACTOR_VERSION 16 → 17, so indexes rebuild once.

…calls

An evaluation on vite, TypeScript's Go port, django, terraform and ripgrep
found answers an agent would take as complete while they were not:

- callers: the per-file call-site cap (512) cut test files that call the
  function under test hundreds of times, silently. vite `callers
  resolveConfig` answered 56 of 68 sites, terraform `NewContext` 53 of 78.
  The cap is now 8192 (the TypeScript repo's index grows by 1%, no slower),
  a record the cap still cuts carries `callsCapped`, and `callers`/`refs`
  name such files in a `coverage` field.
- A file over --max-bytes was invisible: `refs NewChecker` answered
  `{defs: []}` and `outline checker.go` "no such file". The walk now keeps
  the oversized files; `callers`, `refs` (coverage.notIndexed), `find`
  (stderr), `outline`, `symbol-at` and `complexity` name the file and the
  --max-bytes value that indexes it. CLI and MCP alike.
- Rust: `crate::f()` and `super::f()` carry their path as the receiver and
  bind to the crate root or parent module, private items included; a call
  never binds to a `mod` declaration of the same name (`mod search;` took
  every `search()` call in ripgrep's main.rs).
- `incremental.NewProgram(compiler.NewProgram())` kept one call: sites are
  now deduped by name, line and receiver on both tiers, and a caller line
  is listed once when both calls reach the same declaration.

Performance: `subtokens` reads ASCII with ASCII classes (same tokens, the
Unicode split cost search 130 ms on the TypeScript repo) and the self-index
guard compares one precomputed prefix instead of a path.relative per file.
search on that repo is back to 2.31.5's time.

EXTRACTOR_VERSION 16 -> 17.
…is its own crate

Found by the audit of the previous commit. Inside an inline mod block such as #[cfg(test)] mod tests, super::parse names the enclosing file, and was bound to the parent module's homonym (private items included). A file directly under src/bin/, examples/, tests/ or benches/ is a crate root of its own, so its crate::setup() bound to src/lib.rs instead of itself.
@maxgfr
maxgfr merged commit dc6b0a8 into main Oct 12, 2026
2 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 12, 2026
## [2.31.8](v2.31.7...v2.31.8) (2026-10-12)

### Bug Fixes

* say what an answer could not see; bind Rust paths and same-line calls ([#34](#34)) ([dc6b0a8](dc6b0a8))
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.31.8 🎉

The release is available on:

Your semantic-release bot 📦🚀

@maxgfr
maxgfr deleted the fix-eval-findings branch October 12, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant