Skip to content

Code Analysis Rust Trait Impls

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

Rust trait impl call evidence

Validated in Draft, not Labs: #1286, head 3a1ac77a8f1855457ecb660e8f8280e34f8e337b, targets the #1283 source branch codex/code-analysis-labs-integration-review-20261108. No merge, approval, release, installation or labs/code-analysis update. CI run 42465518271 succeeded at 3a1ac77a8 (test 18/20/24, full-regression, browser-regression, Windows portability, package smoke, zip-freshness, website); deploy jobs were skipped by design.

Question

A maintainer changed one method inside impl Trait for Type. Which calls definitely point to that implementation, which only prove use of the trait method, and which remain unknown?

Model

Rust rust-source-direct-v5 / adapter revision 5 captures local trait declarations and impl-method edges.

  • <Type as Trait>::method(...) and unambiguous concrete receivers resolve to the unique captured impl (rust-trait-impl).
  • T: Trait, dyn Trait, Trait::method and generic paths resolve to the trait method declaration only (rust-trait-method-candidate).
  • Change questions add traitCandidates with runtimeTarget: "not-determined", separate from direct knownReferences.
  • A concrete receiver implementing several same-named traits stays unresolved rather than choosing by name; an inherent method with the same name blocks trait selection.

Fixed source answer

Expectations were frozen in benchmarks/code-analysis-rust-trait-change/source-first.json before either CLI ran. Profile: rustc/cargo 1.89.0, aarch64-apple-darwin, default features, tests excluded, root module only.

Project Change Definite impl Trait-only candidate Wrong / missed
tokio-rs/bytes d38faf7→c08f876 BytesMut::put body 2: src/buf/chain.rs:184,185 0 0 / 0
rust-lang/log 761461a→db14597 both KVs::into_kvs impls 0 1: src/__private_api.rs:101 0 / 0

Baseline 0c81af0e reports 0 known references and no candidate coverage. Candidate reports all 2 definite and 1 candidate records under the 40-record display bound.

Example: BytesMut::put at src/bytes_mut.rs:1300 changed; ret.put(&mut self.a) at src/buf/chain.rs:184 reaches that impl because ret is a local crate::BytesMut. The third source-level definite call, src/buf/buf_impl.rs:2374, is inside a Buf default-method body and remains outside the current call inventory; it is reported as an independent unknown rather than a missed trait target.

The log reference-self impl (src/__private_api.rs:25) is head-only because its qualname embeds the changed Key token text; its head traitCandidates still contain src/__private_api.rs:101.

Controls and independent comparison

  • Fixture: two traits with the same method, two types implementing one trait, explicit qualification, T: Trait, &dyn Trait, and an ambiguous concrete receiver.
  • Negative control swaps <A as Left>::act to Right::act; scoring must fail on declaration range. The runner exits nonzero otherwise.
  • rust-analyzer 1.89.0 Go to Definition: both bytes calls go to src/bytes_mut.rs:1300; the log generic call goes to the trait declaration src/__private_api.rs:17, not an impl.
  • Unpacked archify.zip SHA256 5c9687d0fb0fe1ade96defa923e6f7d1c7eb2822d29b12b647b8d9b1d31e35e1 reproduces the same counts and controls.

Limits

Local captured traits only; external, macro-generated, blanket and supertrait impls remain unknown. Receiver typing covers parameters, local let initializers and literal/constructor paths; fields, chained calls and reassigned locals remain unknown. Trait default bodies are outside the call inventory. Same-type same-method impls in different traits share a qualname slot (duplicate-slot) while their head candidates stay inspectable. Source navigation is not compiler, runtime or complete-impact proof.

Reproduction: benchmarks/code-analysis-rust-trait-change/run.py with both pinned sample pairs, the baseline checkout and the source or unpacked ZIP CLI; audit.py reproduces the language-server rows. evidence/ holds normalized run, ZIP and audit summaries.

Decision input: keep improving the built-in Rust source model. Explicit and uniquely typed concrete calls can be separated from trait-only candidates without adopting rust-analyzer as a product dependency.

Clone this wiki locally