Files
codegraph/__tests__
Colby MchenryandClaude Opus 5.5 8fdc8a1efb fix(rust): calls on field chains, struct literals and outside-type paths link by type (#2831)
Issue #2614 reported four Rust calls that linked to a same-named project
method. Case 1 (a slice's contains) was fixed on main by the typed-receiver
work. The other three still reproduced on main in both engines:
vis.map.get("a") on a HashMap field went to Ext::get, J::from(i) under
`use serde_json::Value as J` to a local `impl From<io::Error> for Fail`, and
Xyz { x: 1.0 }.to_val() to Stat::to_val.

Root cause. The extractor keeps one receiver level on a call, so a deeper
field chain (vis.map.get, self.a.b.m, self.0.m) or a struct literal reaches
the resolver as the bare method name, and the typed-receiver reading only
ran for x.m and self.field.m refs. The name strategies then took the one
project get, or one of the two to_val impls. J::from matched no qualified
name, J names no project type, and a single capital letter is read as a
possible generic parameter, so Strategy 3 took the crate's one from. The
same family: under an unrenamed `use serde_json::Value`, Value::default()
linked by qualified name to a project Value's impl.

Fix.
- matchRustWrittenReceiverCall, an exclusive hook beside the as_mut one:
  for a bare-named call, read the receiver from the text at the ref's
  column. Only a field chain rooted at a local, a parameter or self, or a
  struct literal (alone or in parentheses) is read; it is typed with
  rustValueType and the call resolved with rustTypedMethodCall. Any other
  receiver, an unreadable one, or a type no node names (one a macro
  declares) is left to the name strategies. A provided method of a project
  trait the type derives counts (axum-extra's #[derive(TypedPath)]).
- rustFieldValue reads an element of a tuple-typed field (self.pair.0).
- isRustPathCallReachable in gateRustScope: a call through a type path
  whose type the file's use, or the written path, names from std or a
  dependency reaches only the project's impl of a trait for that type, or
  for a trait's path the project's impls of that trait. A path dependency
  the project holds is the project's.

Validation.
- New __tests__/rust-written-receivers.test.ts (12 tests: the issue's
  crate verbatim, chain/literal/derive/path variants, guards): 9 fail on
  main's sources, all pass with the fix. The 27 Rust test files plus
  resolution and cross-language resolution pass.
- A/B against main 5b47bc49 (kernel on), changed call sites triaged as
  removed wrong / added right / wrong to right / same target now by type:
  ripgrep 30 / 18 / 10 / 37 and tokio 281 / 58 / 54 / 141 (every site
  read), axum 18 / 7 / 0 / 7 (every site read), rust-analyzer without
  its parser test data (951 files) 737 / 186 / 434 / 843 (every path
  removal checked by its use; every group sampled). No right link lost.
  Two wrong links added on rust-analyzer: a block-scoped glob
  (`const _: () = { use syntax::ast::*; }`) is read file-wide by the
  existing glob lookup, so a `String` field there reads as ast::String;
  typed locals already misread it the same way on main. Nodes identical
  on every repo; controls gin and express byte-identical.
- Kernel parity (Rust): 1226/1226 files on ripgrep, tokio and axum.
  Resolver-only change, so the kernel needs no mirror.
- Cost: ripgrep median 6.7 s to 6.5 s, tokio 20.2 s to 20.8 s (interleaved,
  median of 3, noisy box); a CPU profile puts about 0.3 s of tokio's 57 s
  busy CPU in the new code and the typed reading it calls.

Fixes #2614

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 06:25:23 +00:00
..