Files
Colby McHenry cd894b78f8 fix(rust): qualify generic/lifetime impl methods by the implementing type, not the trait (#1588)
`impl<T> Source for BufSource<T>` recorded its `read` as `Source::read`: the
receiver rule took the LAST bare `type_identifier` child of the impl_item,
and once the implementing type carries parameters it parses as a
`generic_type`, leaving the trait's identifier as the only bare one. The
method was then unaddressable by its type, collided with the trait's own
declaration, and — carrying the trait's name — the interface-impl
synthesizer treated the impl body as a second declaration and fanned out
dispatch edges from it (a body like `{ 0 }` with no call at all). A lifetime
alone triggered it (`impl<'a> Iterator for Parents<'a>`), as did a reference
implementing type (`impl Trait for &Foo`).

Both extractors now read the grammar's named fields: the implementing type
from `impl_item.type` (generic_type → its bare name, scoped → last segment,
reference → the inner type; tuple / dyn / pointer / primitive → no receiver,
exactly as before) and the trait from `impl_item.trait`. The native kernel
mirrored the old rule bug-for-bug for parity; it changes in lockstep here, so
the parity fixture grows the generic / lifetime / reference / scoped /
generic-trait impl shapes and the design notes drop the "preserve" marker.

ripgrep (110 files): nodes 4029 → 4029; trait-mis-qualified impl methods
61 → 0; synthesized dispatch edges originating outside any trait declaration
38 → 0 while genuine ones rose 33 → 52; plain calls edges unchanged (9098).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LxZj6W6Y1SHXwvpT3uwJpK
2026-08-22 10:53:47 -07:00
..