Skip to content

fix(rust): a turbofish call reaches the function the turbofish wraps - #2720

Merged
colbymchenry merged 2 commits into
mainfrom
claude/rust-turbofish-calls
Oct 21, 2026
Merged

colbymchenry merged 2 commits into
mainfrom
claude/rust-turbofish-calls

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

A Rust call written with a turbofish, like s.get::<u32>(), helper::<u8>() or Pool::<u8>::new(), kept its type arguments in the callee's name (s.get::<u32>). No resolution strategy reads that, so every such call was left unresolved.

Both engines now name the function the turbofish wraps and drop a path's type arguments (Pool::<u8>::new → Pool::new). The call then resolves as it would without the turbofish: on a typed receiver, on self or a field of self, and through an associated-function chain. The kernel and wasm extractors emit the same bytes, and the parity fixture covers nested type arguments and a -> inside them.

Validation

  • __tests__/rust-turbofish-calls.test.ts: 5 cases, all failing on main, all passing in both engines. kernel-rustlang-parity passes with the new shapes in torture.rs.

  • A/B against main 7324faf with fresh indexes, each arm with its own kernel, sites matched by position:

    repo linked removed
    clap +197 0
    dioxus +251 1
    axum +69 0
    tokio +143 0
    serde +48 0
    ripgrep +3 0
    gin, express (controls) byte-identical
    • About 680 of the new links are right: typed method calls (clap's matches.get_one::<String>() → ArgMatches::get_one, dioxus' self.query.new_query::<T>() → QueryEngine::new_query) and generic free functions (tokio's channel::<T>(), dioxus' consume_context::<T>(), serde's assert::<T>()).
    • About 22 are weak guesses at confidence ≤ 0.5. In those, an instance chain's method becomes a bare name, as it already is for the same call without a turbofish: dioxus' .collect::<Vec<_>>() → ServerFunction::collect. Main already makes 23 of those for .collect().
    • The one removal was a wrong link on main: serde_json::from_str::<T>(…).context(…) is no longer guessed as DiffState::context.
    • The 54 sites the diff reports as retargeted are positions shared by a chain's inner and outer calls. At each, an edge was added beside the existing one.
  • Full suite on this exact tree (kernel built, CODEGRAPH_KERNEL_EXPECT=1): 8,037 passed, 0 failed, 82 skipped.

This is the first follow-up from the Rust receiver series' open list (#2719).

🤖 Generated with Claude Code

colbymchenry and others added 2 commits October 20, 2026 19:35
A Rust call written with a turbofish (`s.get::<u32>()`, `helper::<u8>()`,
`Pool::<u8>::new()`) kept its type arguments in the callee's name
(`s.get::<u32>`), which no resolution strategy reads, so every such call
was left unresolved. Both engines now name the function the turbofish
wraps and drop a path's type arguments (`Pool::<u8>::new` is
`Pool::new`), so the call resolves as it would without the turbofish: on
a typed receiver, on `self` or a field of `self`, and through an
associated-function chain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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.

1 participant