feat: resolve C/C++ and Rust calls across files and typed receivers #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/cpp-rust-resolution"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
A dead-code audit found that 93% of C++ symbols had no resolved callers in Brick, so "unused" could not be told apart from "unresolved". This PR makes C/C++ and Rust call resolution good enough for agents to rely on. It also records why a call did not resolve.
C/C++
Calls resolve through the include closure. A header prototype pairs with its definition in another translation unit.
Lookup walks outward through class scopes (including in-repository bases), namespace scopes, and
using namespace/using N::fscopes.staticand anonymous-namespace definitions stay file-local.Member calls resolve only through explicitly declared receiver types:
this;auto x = new T/make_unique<T>;Template parameters stay unknown.
These calls are no longer lost: calls hidden by the most vexing parse (
lock_guard g(f());), and calls in declarations with= {}default arguments (a benign tree-sitter recovery).Casts are no longer counted as calls. Functions returning references and conversion operators now get correct names.
Rust
A crate-wide impl index resolves method calls on these receivers:
self;letbindings;Box/Rc/Arc;Self-returning constructors;dyn Trait.It also resolves
Type::/Self::associated calls.A type name imported from another crate (for example
std::fs::Filenext to a repositoryFile) never matches a repository type, and generics are never guessed.Calls inside expression macros (
assert!,format!,vec!, …) are recovered by re-parsing the macro body.Model (schema 4, optional fields only)
source.unresolved-reason,source.resolutionandsource.extraction.metrics.resolutiongives per-language call-site coverage.Performance: index lookups replace linear scans and per-node ancestor walks, so a YAMS scan now takes 23 s instead of 575 s.
Results
cpp_xtulabeled corpus (new)rust_methodslabeled corpus (new)The unlabeled-repository numbers are coverage only. Spot checks of receiver-typed edges on Fold and Paperbridge found no wrong targets.
Test plan
cargo fmt --check,cargo testandcargo clippy --all-targets -- -D warningspass on this commit alone.source_languages,rust_imports,cpp_xtuandrust_methodslabeled benchmarks are exact over 3 repeats with stable full-model JSON../scripts/quality-gate.shpasses on the full stack.Follow-up: #4 (caller-status queries) is stacked on this branch.
🤖 Generated with Claude Code
C++ calls now resolve through the include closure: header prototypes pair with definitions in other translation units, lookup walks class (including in-repository bases), namespace, and `using` scopes outward, and static or anonymous-namespace definitions stay file-local. Member calls resolve only through explicitly declared receiver types (parameters, locals, fields, this, smart pointers, aliases); template parameters stay unknown. Calls hidden by the most vexing parse are recovered, casts are no longer calls, reference-returning and conversion-operator declarations are named correctly, and benign `= {}` default-argument recoveries no longer drop prototypes or flag files. Rust method calls resolve through a crate-wide impl index for self, typed parameters and lets, struct fields, Self-returning constructors, dyn traits, and Type::/Self:: associated calls, with foreign imports and generics never guessed. Calls inside expression macros are re-parsed. Every unresolved call records source.unresolved-reason, weaker resolutions record source.resolution/source.extraction, and metrics.resolution reports per-language call-site coverage. Declarations gain facts consumed by caller-status queries (qualified names, linkage, virtual, trait impls, attributes, name references, parse-incomplete). C++/Rust External targets include the reason in their identity; out-of-line C++ methods keep their IDs. Linear node/edge scans and per-node ancestor walks are replaced with indexes, cutting a YAMS scan from 575 s to 23 s. New labeled cpp_xtu and rust_methods corpora run three times in the quality gate. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>