Pooling methods across every node sharing a type's bare label is
what makes a split impl block work, but it is only safe when every
one of those nodes really is an impl block for the SAME type. Two
unrelated structs that happen to share a bare name, each with its
own different methods, could still link a caller to a method that
only exists on the wrong one, most concretely when one type
overrides a trait default the other relies on and so never gets an
explicit method node for it.
A struct, enum, or trait declaration gets a contains edge from its
file; an impl block never does. So the type name itself is now
treated as ambiguous, and pooling skipped entirely, whenever two or
more nodes sharing the bare label are real declarations rather than
impl blocks. A single declaration with any number of impl blocks
spread across files, the shape this pass exists for, is unaffected.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit 141662b0eb)
A plain dict assignment silently overwrote an earlier target whenever
two method nodes shared both a source impl node and a stripped
label, which would have kept whichever one was seen last instead of
surfacing the case as the ambiguity it is. The index now keeps a set
per key and folds every match into the candidate set before the
exactly one candidate check runs, so a genuine duplicate still bails
instead of guessing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit 2cbbf1a670)
The check against a pair already having an edge matched on ANY
relation, so a caller that already had, say, a references edge to
the exact same target (from also naming the type elsewhere) silently
suppressed a real call to it. The two relations are not mutually
exclusive and an existing non calls edge says nothing about whether
a call was resolved. Scoped the check to calls edges only, matching
an existing precedent elsewhere in this module for the identical
class of mistake.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit 94735ce241)
Two different structs sharing a bare type name with a colliding
method name must yield no edge rather than a guess, and a self call
to a method that genuinely does not exist anywhere in the corpus
must not fabricate a target.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit afeeefa109)
Covers the issue's own shape (impl Foo split across two files, a
self call in one block reaching a method defined in the other) and a
same file negative control proving the pre existing bare name
resolution is unaffected.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit 2d161af639)