fix(resolver): disambiguate qualified cross-file calls by full namespace tail#479
Open
halindrome wants to merge 2 commits into
Open
fix(resolver): disambiguate qualified cross-file calls by full namespace tail#479halindrome wants to merge 2 commits into
halindrome wants to merge 2 commits into
Conversation
Contributor
Author
QA Round 1 — CLEANReviewer model: claude-opus-4-8 · Contract source: issue #478 · Base: Contract Verification
Findings
Probes that came back clean:
Advisory (non-blocking) — test-coverage hardeningThe code handles these correctly, but the single test does not exercise them, so a future refactor could regress silently:
VerdictCLEAN. Satisfies #478, memory-safe and conservative, compiles under |
Contributor
Author
|
Addressed the QA round 1 advisory test-coverage notes in 66aa971 (test-only, no behavior change):
Full suite green (the lone |
…ace tail cbm_registry_resolve reduced a package/namespace-qualified callee (Foo::Bar::sub) to its bare simple name before the multi-candidate name lookup. When that bare name was defined in several packages, the bare-name scorer (best_by_import_distance) picked one winner deterministically and routed every caller to it — collapsing distinct packages' same-named subs onto a single definition and orphaning the rest. Impact is heaviest for Perl, which has no cross-file LSP and relies entirely on this generic resolver, but the defect applies to any "::"- or "."-qualified callee. Add qualified_suffix_match: when a callee is qualified and its bare name has multiple candidates, pick the sole candidate whose qualified tail matches at a segment boundary (normalizing "::" to "."). Returns the unique match with a new high-confidence "qualified_suffix" strategy; falls through to the existing bare-name scoring when zero or several candidates match. Language agnostic — bare callees contain no separator and are unaffected. Adds resolve_qualified_disambiguates_same_name covering per-package routing of a name defined in three packages, plus the bare-call (no-disambiguation) case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
Harden resolve_qualified_disambiguates_same_name and add a new test per the QA round 1 advisory notes, guarding the fall-through paths against silent regression: - dotted callee form (App.Beta.save) resolves via qualified_suffix - qualified callee matching no candidate tail falls through (not qualified_suffix) - resolve_qualified_ambiguous_tail_falls_through: two candidates sharing the same qualified tail are ambiguous → fall through to bare-name scoring Test-only; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
66aa971 to
3795560
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #478
Problem
A package/namespace-qualified call (e.g. Perl
Foo::Bar::run(...)) whose bare symbol name is defined in more than one package collapses onto a single package.resolve_name_lookupreduces the callee to its bare simple name, and when several candidates share that name the namespace-proximity scorer (best_by_import_distance) deterministically picks one winner — so every*::runcaller routes to the same definition and the others are orphaned (in_degree 0, looking like dead code).This is most visible for Perl, which has no cross-file LSP resolver and depends entirely on this generic registry chain, but the defect applies to any
::/.-qualified callee with a non-unique bare name.Fix
Add
qualified_suffix_match: when a callee is qualified and its bare name has multiple candidates, disambiguate by matching the callee's full qualified tail (normalizing::→.) against each candidate QN at a segment boundary. If exactly one candidate matches, resolve to it with a new high-confidencequalified_suffixstrategy; otherwise fall through to the existing bare-name scoring.Language-agnostic and conservative:
qualified_suffix_matchreturnsNULL→ behavior unchanged.arr->count > 1) and the qualified tail uniquely identifies one candidate; zero or multiple matches fall through to the prior logic.Tests
resolve_qualified_disambiguates_same_name(intests/test_registry.c): a symbol defined in three packages, each fully-qualified call routes to its own package, and a bare call stays ambiguous (noqualified_suffix).Verification
scripts/build.shclean;scripts/test.shpasses (the one unrelatedcli_hook_gate_script_no_predictable_tmp_issue384failure is pre-existing onmain, environment-dependent, and untouched by this change).🤖 Generated with Claude Code