Skip to content

fix(code-index): bind scoped glob and inline-mod use calls - #2294

Merged
ScriptedAlchemy merged 1 commit into
masterfrom
fleet/detail-followups-and-imports-b
Sep 27, 2026
Merged

ScriptedAlchemy merged 1 commit into
masterfrom
fleet/detail-followups-and-imports-b

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

What was wrong

After #2272, a named use inside a function body binds. Two shapes from #2270 still dropped their calls while tracedecay_callers reported complete:

  • A glob use inside a block: fn glob_caller() { use crate::m::*; g(); }.
  • A use inside an inline module: mod inner { use crate::m::h; pub fn inline_caller() { h(); } }.

Import rows are file-scoped. The extractor only modeled top-level uses and named block uses, so these calls reached the seal as bare names with no cross-file authority. There was also no channel from extraction to caller coverage that said "this call site is under an import I could not model". The only gap feed, unresolved_call_sources, carried receiver calls and TypeScript imports.

What changed

  • Typed channel. UnresolvedRef and CodeIndexUnresolvedReferenceV1 gain unmodeled_import: Option<UnmodeledImportShapeV1> (block_glob | inline_module_glob). The field is skipped when None, so existing rows serialize to the same bytes.
    • The seal (unresolved_call_limitations) keeps a marked call as an unresolved caller unless a Calls edge binds its exact callee token.
    • The catalog keys it by its last path segment.
    • CodeGraphInteractiveReader::unresolved_caller_gaps returns UnresolvedCallerGapsV1 { exact_target_unavailable, unmodeled_imports }, and has_unresolved_callers is !gaps.is_empty().
    • tracedecay_callers (application symbol graph) adds PrimitiveSupportGap::import_unmodeled(shape) → omission import_unmodeled. This reuses the fix(code-index): resolve cfg variants and item-list macro bodies #2256 mechanism, so the page is partial with support gap import_unmodeled: <shape>. The typed code_callers path adds OmissionReason::ImportUnmodeled beside the existing Unsupported.
  • Modeling (Rust extractor v16).
    • An inline mod body's use declarations form a scope for that module's functions. self::/super:: resolve against the inline module (file_level_use_path), so super::m::k from one level down becomes self::m::k. Block uses inside inline-module functions get the same treatment.
    • A glob in a block or inline module that names a project module outside the file rewrites a call it could supply into that module (g → crate::m::g), marked with the glob's shape. When it binds, it is a normal NameResolved caller and no gap is reported. When the module does not define the name, it stays a disclosed gap. Rust would then fall through to outer scopes, which the index does not model.
    • Two project globs in one scope mark without rewriting. An external glob (std::collections::*), macros, path roots, and prelude or primitive heads are left alone.
  • Extractor revision extractor.rust.v15 → v16. The rows-digest pin (extract.rs) and the partitioned-codec state and segment pins moved. Their fixtures contain no block, inline-module, or glob use, so only the revision string changed their bytes.
  • OmissionReason::ImportUnmodeled is regenerated into the SDK operations.ts. contracts:check is green.

Fail before / pass after

Run with only rust_extractor.rs restored to origin/master. The new plumbing stayed, so the tests compile.

  • code-extraction rust::inline_module_uses_qualify_calls_against_the_inline_module: master left [("h", None), ("k", None), ("local", None), ("d", None)]; branch right [("crate::m::h", None), ("self::m::k", None), ("local", None), ("d", None)].
  • code-extraction rust::glob_uses_qualify_and_mark_the_calls_they_could_supply: master left [("g", None), ...]; branch [("crate::m::g", Some(BlockGlob)), ("crate::n::named", None), ("Some", None), ("println", None)]. The test also covers two globs (marked, bare), an external glob (untouched), and an inline-module glob (InlineModuleGlob).
  • code_index_suite import_evidence::rust_calls_bind_through_block_globs_and_inline_module_uses: master left []; branch ["…lib.rs::glob_caller", "…lib.rs::globbed::inline_glob_caller"] for m::g, and ["…lib.rs::inner::inline_caller"] for m::h. A glob miss yields unresolved_caller_gaps == {exact_target_unavailable: false, unmodeled_imports: {BlockGlob}}, while m::g yields no gaps.
  • mcp_suite callers_behavior_test::tracedecay_callers_binds_scoped_uses_and_discloses_an_unmodeled_glob drives the issue's fixture through MCP tracedecay_callers. g → glob_caller, h → inline_caller, both complete. only_in_n under a glob miss → partial, omission {"domain":"graph","count":1,"reason":"import_unmodeled"}, support gap import_unmodeled: block_glob. On master, g and h answer complete with no callers (the fix(code-index): calls through block glob or inline-mod use are dropped as complete #2270 reproduction).

Runtime journey (debug CLI from this branch)

The issue's fixture plus a glob miss. Isolated profile, one daemon under systemd-run --user --scope -p MemoryMax=6G -p MemorySwapMax=1G, tracedecay tool tracedecay_callers at depth 1:

== callers of m::g
 completeness complete omissions [] support_gaps []
 callers ['src/lib.rs::glob_caller']
== callers of m::h
 completeness complete omissions [] support_gaps []
 callers ['src/lib.rs::inner::inline_caller']
== callers of m::k
 completeness complete omissions [] support_gaps []
 callers ['src/lib.rs::fn_local']
== callers of n::only_in_n
 completeness partial omissions [{"domain": "graph", "count": 1, "reason": "import_unmodeled"}] support_gaps [{"language": null, "provider": "code_index", "reason": "import_unmodeled: block_glob"}]
 callers []

The #2270 report on master showed completeness complete omissions [] [] for m::g and m::h.

Local verification

Fixes #2270

A glob use inside a block and a use inside an inline mod left their calls
unbound while callers reported complete, and nothing carried the fact that
a call site sat under an import the extractor could not model.

The Rust extractor (v16) now reads an inline module's use declarations
like a block's, with self:: and super:: resolved against the inline
module. A call under a block or inline-module glob is rewritten into the
glob's one project module and marked with a typed UnmodeledImportShapeV1
on the unresolved reference. The seal keeps a marked call that no edge
binds as an unresolved caller, and callers and code_callers report it as
partial with an import_unmodeled omission and a support gap naming the
shape. The rows-digest and partitioned-codec pins move with the revision
string alone.
@changeset-bot

changeset-bot Bot commented Sep 27, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a43c2fa

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ScriptedAlchemy
ScriptedAlchemy merged commit 02d91e5 into master Sep 27, 2026
1 check passed
@ScriptedAlchemy
ScriptedAlchemy deleted the fleet/detail-followups-and-imports-b branch September 27, 2026 05:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a43c2fa16a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +2446 to +2449
if glob_candidate && !scope.globs.is_empty() {
if let [module] = scope.globs.as_slice() {
reference.reference_name =
format!("{module}::{}", reference.reference_name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve module-local items ahead of inline-module globs

When an inline module contains both a glob import and a same-module item with the same name, Rust gives the local item precedence, but this branch unconditionally rewrites the call through the single glob. For example, mod inner { use crate::m::*; fn g() {} fn caller() { g(); } } calls inner::g; if crate::m::g also exists, the extractor instead emits a false call edge to that external function. Check the inline module's own item namespace before qualifying a call through its glob.

Useful? React with 👍 / 👎.

Comment on lines +48 to +49
"crate", "self", "super", "Self", "std", "core", "alloc", "Some", "None", "Ok", "Err", "Box",
"Vec", "String", "Option", "Result", "Default", "drop", "bool", "char", "str", "u8", "u16",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow project globs to supply prelude-shaped names

A project module can legally export names from this exemption list, and a scoped glob can resolve them ahead of the prelude; for example, mod m { pub fn drop() {} } followed by use crate::m::*; drop(); calls m::drop. Exempting drop leaves the reference bare, after which the cross-file blocklist suppresses it and no unmodeled_import gap is recorded, so callers can report a complete result while omitting the real edge. These names need project-glob resolution rather than a fixed exemption.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-27T05:19:02.859254Z a43c2fa PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(code-index): calls through block glob or inline-mod use are dropped as complete

1 participant