You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A Rust method declared only on a supertrait is attributed to the subtrait, fabricating an identity #374
A generic parameter bound to a trait that declares no methods of its own but
extends (: SuperTrait) one that does resolves a method call to the subtrait instead of the trait that actually declares the method. Real Rust
resolves through the supertrait; crypto-finder attributes the call to a trait
that never declares it — a fabricated identity, not a missing one.
Reproduction
mod foo {pubtraitSuperTrait{fndescribe(&self) -> &'staticstr{"super"}}}traitTrait1: foo::SuperTrait{}structMarker;impl foo::SuperTraitforMarker{}implTrait1forMarker{}fntest<T:Trait1>(x:&T) -> &'staticstr{
x.describe()}
Confirmed against a real rustc build (compiles, prints "super") and
matches rust-analyzer's own super_trait_method_resolution test.
crypto-finder resolves the call to app.Trait1.describe — Trait1 never
declares describe.
Why it is not a quick patch
rustFirstTraitBound (internal/callgraph/rust_type_semantics.go) has no
notion of supertrait relationships. Fixing it needs two facts that do not
exist today:
A trait-declares-method-name table, independent of return type. fnReturns looks reusable but silently omits every void method
(recordReturn returns early when ret == "") — exactly the
crypto-relevant shape (fn update(&mut self, data: &[u8]) returns
nothing). Reusing it would make the fix wrong for the methods that matter
most, not just incomplete.
A supertrait graph (trait Trait1: SuperTrait, OtherTrait {} can list
several) to walk when the directly bound trait does not own the called
method, with the same "first bound, no ambiguity resolution" policy used
elsewhere.
Suggested approach
Build the trait-declares-method-name fact first (cheap, mechanical: walk trait_item bodies collecting every fn name regardless of return type),
verify it does not regress the existing 140+ Rust tests, then add the
supertrait graph walk on top, one bound trait at a time, with a real rustc-validated fixture for each new case.
Crypto relevance
Not sized against a corpus, but confirmed real in principle: RustCrypto's own
trait hierarchies use supertraits (e.g. AeadInPlace: AeadCore), so a
generic function bound to a supertrait-extending trait and calling a
supertrait method would misattribute the call.
References
Documented in openspec/specs/rust-callgraph-identity-resolution/spec.md,
"Known gaps" → "A method declared only on a supertrait is attributed to the
subtrait".
Pinned by TestRustParser_SupertraitBoundMethodIsAKnownUnfixedGap
(internal/callgraph/rust_analyzer_rustc_parity_test.go) — asserts the
current (fabricated) identity so a future fix updates this test
deliberately instead of silently.
Governing rule for this capability: "a wrong identity is worse than no
identity" — this call site should carry no identity rather than the wrong
one, until the fix above lands.
Summary
A generic parameter bound to a trait that declares no methods of its own but
extends (
: SuperTrait) one that does resolves a method call to thesubtrait instead of the trait that actually declares the method. Real Rust
resolves through the supertrait; crypto-finder attributes the call to a trait
that never declares it — a fabricated identity, not a missing one.
Reproduction
Confirmed against a real
rustcbuild (compiles, prints"super") andmatches rust-analyzer's own
super_trait_method_resolutiontest.crypto-finder resolves the call to
app.Trait1.describe—Trait1neverdeclares
describe.Why it is not a quick patch
rustFirstTraitBound(internal/callgraph/rust_type_semantics.go) has nonotion of supertrait relationships. Fixing it needs two facts that do not
exist today:
fnReturnslooks reusable but silently omits every void method(
recordReturnreturns early whenret == "") — exactly thecrypto-relevant shape (
fn update(&mut self, data: &[u8])returnsnothing). Reusing it would make the fix wrong for the methods that matter
most, not just incomplete.
trait Trait1: SuperTrait, OtherTrait {}can listseveral) to walk when the directly bound trait does not own the called
method, with the same "first bound, no ambiguity resolution" policy used
elsewhere.
Suggested approach
Build the trait-declares-method-name fact first (cheap, mechanical: walk
trait_itembodies collecting everyfnname regardless of return type),verify it does not regress the existing 140+ Rust tests, then add the
supertrait graph walk on top, one bound trait at a time, with a real
rustc-validated fixture for each new case.Crypto relevance
Not sized against a corpus, but confirmed real in principle: RustCrypto's own
trait hierarchies use supertraits (e.g.
AeadInPlace: AeadCore), so ageneric function bound to a supertrait-extending trait and calling a
supertrait method would misattribute the call.
References
openspec/specs/rust-callgraph-identity-resolution/spec.md,"Known gaps" → "A method declared only on a supertrait is attributed to the
subtrait".
TestRustParser_SupertraitBoundMethodIsAKnownUnfixedGap(
internal/callgraph/rust_analyzer_rustc_parity_test.go) — asserts thecurrent (fabricated) identity so a future fix updates this test
deliberately instead of silently.
suites.
Governing rule for this capability: "a wrong identity is worse than no
identity" — this call site should carry no identity rather than the wrong
one, until the fix above lands.