Repository navigation
fix(rust): generic impl methods source their own calls (#763 Rust share) - #2685
Merged
Merged
Conversation
The def side names a Rust impl method after the implementing type with its generic arguments stripped (`impl<T> Gen<T>` -> `Gen`, extract_rust_impl). The call-scope QN in extract_unified.c used the impl's type text verbatim, `Gen<T>` / `Life<'a>`. So every method of a generic or lifetime-parameterised impl had a scope QN that no node carries, and every call in its body was sourced from the File node instead of the method. Base census, 9f85f10 par (lane L7's #763 measurement): 87,855 Rust CALLS start at a File/Module node, 84,331 of them (96%) on a line inside a function span. Go is 0%. Strip the generic arguments on the call side exactly as the def side does. Plain impls, trait impls, free functions and inline modules were already consistent (checked on a fixture with the base binary). Test: extract_rust_generic_impl_call_scope_matches_def (plain, type-generic and lifetime-generic impls; def QN == call scope). Refs #763 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…h resolvers) Sequential and parallel pipeline twin of extract_rust_generic_impl_call_scope_matches_def: the calls in a type-generic and a lifetime-generic impl method are sourced from the method, not from the File node. Refs #763 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…-call-scope Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The extractor fix above names a generic impl's methods `Gen.in_generic` on both the def and the call-scope side. The Rust LSP still built its self type from the impl's raw text, `Gen<T>`. That broke three things: - its caller QN (`Gen<T>.in_generic`) no longer joined the pipeline's call scope, so every LSP row inside a generic or lifetime impl was dropped for a registry guess. On 9 Rust repos that turned 1,927 lsp_* edges into suffix_match/unique_name; - `self.` and `Self::` dispatch never found the impl's own methods; `Self::assoc_g()` had no edge at all, on main as well; - the return-type harvest never matched those methods, so chained calls on them stayed untyped. Strip the generic arguments from the impl's self type in both places. Text that starts with `<` (a qualified path) is left alone. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
cppcheck 2.20 reports the post-cut `if (!name[0])` as always false (knownConditionTrueFalse): it cannot see that writing through `lt` may empty `name`. The name is non-empty here, so the cut empties it only when `<` is the first character. Test exactly that before the cut. The behaviour is unchanged. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…Smart CI selection fix #2684) Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…-call-scope Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com> # Conflicts: # tests/test_pipeline.c
DeusData
added a commit
to ilyabrykau-orca/codebase-memory-mcp
that referenced
this pull request
Oct 19, 2026
Brings in main 658639e (DeusData#2685, Rust generic-impl call scope). One conflict in tests/test_extraction.c: main's new F-R4 test and its helper sit right before the flag-exempt test, whose comment this branch rewrote (Go now sets is_method, so the guarded language is Rust). Both are kept: main's block, then this branch's comment. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
DeusData
added a commit
to ilyabrykau-orca/codebase-memory-mcp
that referenced
this pull request
Oct 19, 2026
Brings in the base branch with main 658639e merged (DeusData#2685, Rust generic-impl call scope), so this branch merges cleanly into main again. No conflicts. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
This is the Rust share of #763: calls inside the methods of a generic impl were sourced from the File node.
For
impl<T> Gen<T>andimpl<'a> Life<'a>, the extractor's call scope kept the type arguments (Gen<T>.in_generic). The def side strips them (Gen.in_generic, asextract_rust_impldoes). As a result, no node carried the scope QN, and every call in those methods fell back to the File node. Plain impls, trait impls, free functions and inline modules were already correct.The first commit strips the generic arguments from a Rust
impl_itemname in the class-scope QN (extract_unified.c).A second commit, which the corpus proof forced
The Rust LSP also built an impl's self type from the raw text
Gen<T>. Before the first commit, both sides used the same wrong name, so the LSP rows still joined their calls (onto the File node). After it, the LSP caller QNGen<T>.in_genericno longer matched the fixed scopeGen.in_generic.On 9 Rust repos, the first commit alone turned 1,927 LSP-resolved edges into registry name guesses (
lsp_direct518,lsp_short_name_unique973,lsp_ufcs182,lsp_constructor114,lsp_method_dispatch108 and others).The same mismatch was already broken on
main, independently of the first commit. Inside a generic impl,self.other()got onlyunique_name, andSelf::assoc()had no edge at all. In a plain impl, the same calls getlsp_method_dispatchandlsp_direct. The return-type harvest (Phase B2) also never matched generic-impl methods, so chained calls on them stayed untyped.The second commit adds
rust_strip_impl_type_args, used inrust_process_impland in Phase B2. A third commit reshapes the empty-name check so that cppcheck 2.20 accepts it; behaviour is unchanged.Evidence
Base
9f85f104vs this branch (headfed5cbf9, currentmainmerged in). Setup: same machine, production binaries, 9 pinned Rust repos (diesel, helix, meilisearch, nushell, qdrant, cargo, tauri, tokio, typst). Every repo was indexed twice with the parallel resolver, and both runs were identical for every edge type.#763 metric: Rust CALLS sourced at a File/Module node while the call sits inside a function span go from 22,287 to 1,572 (−93%). Total Rust CALLS go from 274,055 to 283,478. That rise is collapsed File edges splitting into one edge per calling method.
LSP accounting (same call sites, base -> this PR): the first commit's loss is gone.
lsp_method_dispatchlsp_directlsp_ufcslsp_trait_dispatchlsp_constructorlsp_short_name_uniqueIndependent oracle (rust-analyzer SCIP, all 9 repos): recall rises on 9 of 9 repos, and precision rises or stays equal on 9 of 9.
The 1,572 File-sourced calls that remain are a separate shape, not investigated here. Many are multi-line chained callees, such as diesel's
transaction_manager\n.status\n.set_....Tests
extract_rust_generic_impl_call_scope_matches_def: the call scope of a generic and of a lifetime impl method equals its def QN.pipeline_rust_generic_impl_method_sources_its_calls(sequential and parallel):lsp_*strategy (helper_a,self.other_g(),self.other_l());Self::assoc_g()has an edge.All three fail with the production change reverted, for the asserted reason, and pass with it. Each half was also shown separately with production binaries on a fixture:
unique_name.lsp_constructor,lsp_method_dispatchandlsp_direct, as in a plain impl.Note for merging
This branch and #2681 both add Rust tests at the same spot in
tests/test_pipeline.c. Whichever lands second must mergemainagain and keep both blocks. Nothing else overlaps;rust_lsp.cmerges cleanly.Checklist
git commit -s)extract_unified.c; memory-core linter passes