Skip to content

fix(rust): use bindings follow Rust's scopes, and module paths walk the crate's modules - #3014

Merged
colbymchenry merged 1 commit into
mainfrom
claude/rust-use-bindings-on-main
Oct 29, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
claude/rust-use-bindings-on-main

Conversation

@colbymchenry

@colbymchenry colbymchenry commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

Builds on #2308 by @danusha2345 (its module-path part landed as #2955): Rust use bindings now follow Rust's scopes, on main's own use model instead of a second parser.

  • A renamed use (use crate::util::take as consume; consume()) links to the item its path names.
  • A use written in a function or a block binds its name there only, ahead of the module's uses and the file's own items.
  • A call to a parameter, closure or let of a function's name links to nothing, not to the function; a let holding a function by its path (let test = test::<i8>;) calls that function.
  • use crate::models::E::Good; Good(1) links to that enum's variant.
  • Module paths (resolveRustPathReference) walk the crate's modules (rustWalkModules + rustModuleItems) from the module they are written in: super::x() / crate::x() with no module between, super inside an inline mod tests { }, items passed on with pub use or globs, and other workspace crates by the names their manifests give them.

Root cause

  • isRustNameInScope took every use of a name in the file (rustUseItems), wherever it was written, and only items carry names, so a rename had nothing to match.
  • Nothing read the locals around a bare call.
  • resolveRustPathReference mapped a path to a file by directory (resolveRustModuleFile), so a path with nothing between super/crate and its item had no file, super in an inline module went to the directory's parent, and re-exports and other crates were never followed.

Fix

  • One use reader, rustUsesOf: each use keeps the block it is written in (rust-scopes-style braces; an inline mod and a macro's braces, cfg_if!'s nested ones included, are the module's), std uses are kept with their positions, and the text is read with strings blanked (blankRustCode), so a string's "use crate::x;" binds nothing.
  • rustVisibleUse: the innermost scope's bindings at a reference. isRustNameInScope uses it (rustUseItemsAt), falling back to the whole file's when nothing binds the name there.
  • matchRustUseBoundName, ahead of the pre-filter: renames, and locals via rust-scopes' rustBindingAt (a nested fn sees none of its parent's; a block's use nearer than the local wins).
  • rustUsePathItems: an enum parent's variant.
  • rustPathTarget (behind resolveRustPathReference): the module walk, with today's 2015 crate-root fallback; a Type::member path is skipped here (as before, it names no module item).
  • rustCrateGraph: package names read by section (axum-core writes categories = [..] before name; the crate was missing from the graph), and [lib]/[[bin]] paths of their own (ripgrep's crates/core/main.rs), which crate:: starts from. A file no manifest covers (sources indexed without their Cargo.toml) starts crate:: from the nearest lib.rs/main.rs above it, as the directory walk did (extraction.test.ts's manifest-less database::profiles::find() case).
  • Retired: resolveRustModuleFile, collectRustUseBindings (isBoundToOutOfRepoImport now reads rustUsesOf's std uses), rustItemPlacement.

Validation

  • Tests: PR fix(rust): resolve bare calls through exact use bindings #2308's rust-use-call.test.ts (15 cases, credited), new rust-use-scopes.test.ts (its parser-level scenarios as call edges, plus held functions and macro braces), rust-crate-roots.test.ts, and 5 new rust-module-path-call cases. On main's resolution source 18 of the 32 fail; with the fix all pass. All 34 Rust-related suites pass (292 tests).

  • A/B on main (01e0ac3; re-checked on 13f983d and 86c85cf), 7 Rust repos, the same sites on the native kernel and on wasm:

    repo sites added removed moved notes
    tokio 2,434 159 39 +1,354 calls (mpsc::channel, task::spawn → tokio-test's, tokio::task::yield_now), +1,053 imports; removed: 152 locals passed or called, 6 std Results, 1 import through a #[path] module
    ripgrep 248 149 0 removed: locals (build(matcher, searcher, printer)), a block's use std::os::unix::fs::symlink
    axum 710 60 10 axum-core/-extra/-macros now in the crate graph; removed: locals, Request under use http::Request
    clap 730 112 1 ClapResult / ClapError renames now link; removed: locals
    serde 155 207 15 removed: 192 calls to a closure let test = |value, tokens| test(…) (its body keeps the edge)
    dioxus 2,950 272 14 removed: locals, std Ok(…) main took for dioxus-core's fn Ok via a use read from a string
    gleam 1,573 359 56 moved: Error from a framework guess to the used error::Error enum

    Triage: every group inspected with samples (all right); every added or moved target's crate checked against the source crate's manifest dependencies (the only cross-direction ones are trait → implementation edges). express and flask byte-identical. Known loss: tokio's use crate::process::unix::GlobalOrphanQueue, where unix passes on super::imp::* and imp is one of two cfg-alternative #[path] modules (unix/mod.rs, windows.rs); main found it by the directory's name, and a module that depends on the build stays unread (fix(rust): resolve use super::* callees in #[path] modules #1892's follow-up keeps it so).

  • Cost (kernel, medians of 3 interleaved runs):

    repo CPU peak RSS
    tokio 34.5 → 33.0 s 991 → 1,007 MB
    gleam 32.5 → 30.6 s 1,022 → 1,012 MB
    dioxus 45.4 → 45.4 s 1,101 → 1,107 MB

    (A first version walked every Type::member path too and cost ~40 MB on tokio; such paths now skip the walk, since they name no module item.)

  • Full suite (kernel, CODEGRAPH_KERNEL_EXPECT=1, daemon allowed, one worker) on this commit, on e7c9ffd: 784 files (778 passed, 6 skipped); 9,366 tests: 9,281 passed, 0 failed, 85 skipped.

Left out

🤖 Generated with Claude Code

…he crate's modules

A bare Rust name took the file's `use`s all at once: a `use` inside one
function (`fn first() { use crate::util::take; take() }`) bound `take` for
every other function too, and for the file's own `fn take`; a renamed one
(`use crate::util::take as consume; consume()`) linked nothing, since no
item carries the alias; a parameter or closure of the function's name
(`fn run(take: fn()) { take() }`, `let take = || {};`) linked to the
imported function; and `use crate::models::E::Good; Good(1)` took any
`E::Good`. Paths through modules (`resolveRustPathReference`) walked the
directories instead of the modules: `super::helper()` and `crate::config()`
with no module between linked nothing, `super` inside an inline
`mod tests { }` went to the parent directory's module, and an item a module
passes on (`pub use`, a glob) or another workspace crate's was not found.

The fix keeps one `use` reader, rustUsesOf:
- each `use` keeps the block it is written in (a function's body or a
  block; an inline `mod` and a macro's braces, `cfg_if!`'s nested ones
  included, are the module's), and std `use`s are kept by position;
- a reference reads the binding of its innermost scope (rustVisibleUse);
  isRustNameInScope uses it, so a block's `use` shadows the file's own item
  and a variant `use` names its enum's variant (rustUsePathItems' enum tail);
- matchRustUseBoundName, ahead of the pre-filter, resolves a rename to the
  item its path names, and a call to a name a local binds (rust-scopes'
  bindings, nearer than any `use`) to nothing, unless the local is a `let`
  holding a function by its path (serde's `let test = test::<i8>;`);
- resolveRustPathReference is rustWalkModules + rustModuleItems from the
  module the path is written in (rustPathTarget), with today's crate-root
  fallback; resolveRustModuleFile, collectRustUseBindings and
  rustItemPlacement are gone, and isBoundToOutOfRepoImport reads
  rustUsesOf's std `use`s;
- `use`s are read with strings blanked (blankRustCode), so a string's
  "use crate::x;" binds nothing;
- the crate graph reads a package's name by its section (axum-core writes
  `categories = [..]` first) and a `[lib]`/`[[bin]]` path of its own
  (ripgrep's `crates/core/main.rs`), which `crate::` then starts from; a
  file no manifest covers starts it from the nearest lib.rs or main.rs
  above it, as the directory walk did.

Validation:
- rust-use-call.test.ts (PR 2308's 15 cases), rust-use-scopes.test.ts,
  rust-crate-roots.test.ts and 5 new rust-module-path-call cases: on main's
  source 18 of 32 fail; all pass. Every rust-* suite passes.
- A/B on main 01e0ac3, 7 repos, the same sites on the kernel and on wasm:
  tokio +2,434 sites (1,354 calls, 1,053 imports), 159 removed (152 locals
  called or passed as values, 6 `Result`s std's, 1 import through a path
  attribute module); ripgrep +248 / -149; axum +710 / -60; clap +730 / -112;
  serde +155 / -207 (192 calls to a closure named `test`); dioxus
  +2,950 / -272; gleam +1,573 / -359. Groups and samples inspected, every
  changed site's crate checked against the manifests' dependencies;
  express and flask byte-identical.
- Cost (kernel, medians of 3 interleaved): tokio CPU 34.5 -> 33.0 s, peak
  RSS 991 -> 1,007 MB; gleam 32.5 -> 30.6 s, 1,022 -> 1,012 MB; dioxus
  45.4 -> 45.4 s, 1,101 -> 1,107 MB.
- Original PR #2308 by @danusha2345; its module-path part landed as PR #2955.

Co-authored-by: danusha2345 <ewidusoc498@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry
colbymchenry force-pushed the claude/rust-use-bindings-on-main branch from c55fd60 to 40e6e19 Compare October 29, 2026 17:26
@colbymchenry
colbymchenry merged commit 4955eac into main Oct 29, 2026
@colbymchenry
colbymchenry deleted the claude/rust-use-bindings-on-main branch October 29, 2026 18:39
inth3shadows added a commit to inth3shadows/codegraph that referenced this pull request Oct 29, 2026
Brings 4955eac..787eafb (colbymchenry#3014, colbymchenry#3017, colbymchenry#3020, colbymchenry#3018, colbymchenry#3023). Clean
auto-merge. README: drop colbymchenry#2871 (closed upstream; colbymchenry#2934 merged in its
place, and name-matcher already matches upstream).
colbymchenry added a commit that referenced this pull request Oct 29, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (isInsideProject, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  11 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 57dc7ae): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 29, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on a38a1ec): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 29, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on a38a1ec): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on a38a1ec): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request Oct 30, 2026
…'s own function (#3025)

A Rust call through a type, `sim::items::ItemPool::for_def(…)` into another
crate of the workspace or `ItemPool::for_def(…)` under `use
sim::items::ItemPool;`, was matched by its qualified name alone, so a
namesake type's function in another crate or module could take it (a
workspace's `client` crate's `ItemPool::for_def`). The module walk stopped
at the type, a `use` of a `pub const` or `static` (`use sim::RANK_COUNT;`)
linked nothing, and a type rustfmt wrapped below its path (`h:
&scheduler::\n Handle`) linked by the file's `use` of its last name.

The fix, on the module walk:
- rustPathTarget reads `Type::member` calls: the type is the item the
  path's modules name, or the one the `use` that binds its name names
  (rustUseItemsAt), and rustTypeMember finds its member: an enum's variant;
  else the type's own (inherent) function or `const` in the type's crate,
  a trait impl's only when it is the one of that name; a trait's own
  declared method. A type alias, `Self`, a type the module declares itself
  and a type path in any other position are left as they were.
- Module items include `variable`s (a module-level `pub const`/`static`).
- matchRustUseBoundName reads a qualifier written on the line above a
  type (rust-scopes' blanked code, so a commented-out path is none) and
  resolves the whole path.
- Memoized per (type, member) and per path.
- Manifest paths stay inside the project: a workspace member that leaves
  it (`../sibling`, an absolute path) is neither read nor listed
  (escapesRoot, in expandMembers), and rustCrateGraph drops a
  `[lib]`/`[[bin]]` path that leaves it, as it already did a dependency's.

Validation:
- rust-cross-crate.test.ts (PR 2631's 9 cases, credited),
  rust-type-member-paths.test.ts and rust-manifest-paths.test.ts: on main
  10 of 15 fail; all pass. Every rust-* suite passes. On main the workspace
  map read `../outside/Cargo.toml`, `../vendor/x/Cargo.toml` and
  `/abs/crate/Cargo.toml` and listed `../vendor`; now only the project's.
- A/B against main, native kernel, 7 Rust repos (every site the same
  as against PR #3014's own commit; re-checked on 60b0d7a): tokio +205
  links / 139 retargeted / 230 chains gaining their head call, ripgrep
  +155 / 13 / 1, axum +25, clap +179 / 0 / 295, serde +28, dioxus +142 /
  6 / 31, gleam +114 / 47 / 0; 0 removed. Retargets go to the type the
  code imports or its own crate's (tokio's Semaphore::new and loom mocks
  to tokio::sync, ripgrep's Error::from, gleam's Printer::new); express
  and flask byte-identical.
- Cost, native kernel, medians of 3 interleaved runs (dioxus of 7):
  tokio CPU 32.1 -> 29.7 s, peak RSS 1,000 -> 1,010 MB; gleam 29.1 ->
  28.1 s, 1,010 -> 1,004 MB; dioxus 38.7 -> 40.1 s, 1,111 -> 1,115 MB
  (timed on one thread, rustPathTarget 1.24 -> 1.32 s over 17,198 calls).

Builds on PR #2631 by @BGamboa13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant