Everything one index pass yields: binds to in-corpus definitions plus
the synthesized dependency surface (D29) for references whose symbol
has no definition occurrence anywhere in the corpus.
Dynamic-dispatch fan-out edges: for every impl block naming a trait the
corpus defines, trait_method -> impl_method (Calls, Dynamic) for each
method the impl defines under a same-named trait method. Conservative
over-approximation — every impl is assumed reachable through the trait —
which is exactly why the edges carry the distinct Dynamic evidence.
Pairing rule: the impl block names the trait (same file/module, or a
named import) and the method names match.
Merge several on-disk indexes into one file: documents and external
symbols concatenate, metadata comes from the first. Per-language
indexers cover disjoint files, so concatenation is the whole merge.
Resolve references against FOREIGN definitions using import evidence
only — the cross-repo boundary pass. Same-file/module/receiver/local
tiers are intra-repo by definition and deliberately excluded, which
also prevents false bindings between identically-named files in
different members. refs and owner_imports come from one member;
foreign_nodes from the others.
Bind our extracted references using a compiler-produced SCIP index —
the highest evidence tier. A reference binds when a SCIP reference
occurrence overlaps its span and the symbol’s definition occurrence
falls inside one of our nodes. read_source maps a repo-relative path
to its content (for line→byte conversion); return None to skip a file.