Skip to content

fix(rust): never let a std-typed receiver bind a same-named project method (#2053) - #2339

Merged
DeusData merged 1 commit into
mainfrom
fix/issue-2053
Sep 30, 2026
Merged

DeusData merged 1 commit into
mainfrom
fix/issue-2053

Conversation

@DeusData

Copy link
Copy Markdown
Owner

The Rust LSP types root: &Path and dispatches root.join(..) to
std.path.Path.join, a registered seed method with no graph node. Both
call resolvers treated "LSP row without a gbuf target" like "no LSP row"
and fell back to the textual registry, which bound the call to the only
project method named join (EvidenceTier::join via unique_name). Every
std/seeded-crate call whose leaf name a project method shares was
fabricated this way.

cbm_pipeline_rust_external_target() (lsp_resolve.h) recognises a Rust row
whose strategy emits a registered target (method/trait/deref/bound
dispatch, direct, ufcs, constructor) and whose QN lies outside the
project prefix. Project defs are registered under project-prefixed QNs, so
such a target is a std/core/alloc or seeded-crate symbol by construction.
pass_calls.c and pass_parallel.c skip the registry fallback for those rows
(in lockstep), and the parallel route-method fallback no longer turns a
skipped map.get(k) into a source->source self-call. Project-prefixed
rows, unknown-receiver rows and every other language are unchanged.

The call-expression receiver (root.to_path_buf().join(..)) needed type
facts: Path::join/to_path_buf/with_extension/with_file_name now return
PathBuf, PathBuf::as_path returns Path, and PathBuf derefs to Path.

Measured on BurntSushi/ripgrep @ 3fce3b5 (fresh index, two runs each,
byte-identical): CALLS 5371 -> 5014; 357 removed (307 suffix_match,
45 unique_name, 5 field_type_hint), 0 added, no lsp_* edge touched.
Removed samples are all std receivers (String::new -> State.new,
msg.contains -> ByteSet.contains, alts.push on a Vec -> TSeq.push).


Touches the call resolvers (pass_calls.c / pass_parallel.c) like the #1916 PR.

Fixes #2053

…ethod (#2053)

The Rust LSP types `root: &Path` and dispatches `root.join(..)` to
std.path.Path.join, a registered seed method with no graph node. Both
call resolvers treated "LSP row without a gbuf target" like "no LSP row"
and fell back to the textual registry, which bound the call to the only
project method named `join` (EvidenceTier::join via unique_name). Every
std/seeded-crate call whose leaf name a project method shares was
fabricated this way.

cbm_pipeline_rust_external_target() (lsp_resolve.h) recognises a Rust row
whose strategy emits a registered target (method/trait/deref/bound
dispatch, direct, ufcs, constructor) and whose QN lies outside the
project prefix. Project defs are registered under project-prefixed QNs, so
such a target is a std/core/alloc or seeded-crate symbol by construction.
pass_calls.c and pass_parallel.c skip the registry fallback for those rows
(in lockstep), and the parallel route-method fallback no longer turns a
skipped `map.get(k)` into a source->source self-call. Project-prefixed
rows, unknown-receiver rows and every other language are unchanged.

The call-expression receiver (`root.to_path_buf().join(..)`) needed type
facts: Path::join/to_path_buf/with_extension/with_file_name now return
PathBuf, PathBuf::as_path returns Path, and PathBuf derefs to Path.

Measured on BurntSushi/ripgrep @ 3fce3b5 (fresh index, two runs each,
byte-identical): CALLS 5371 -> 5014; 357 removed (307 suffix_match,
45 unique_name, 5 field_type_hint), 0 added, no lsp_* edge touched.
Removed samples are all std receivers (String::new -> State.new,
msg.contains -> ByteSet.contains, alts.push on a Vec -> TSeq.push).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rust: std-typed receivers hijack same-named project methods, fabricating CALLS edges (37.6% of edges stdlib-shaped on 0.10.8) — minimal repro

1 participant