Repository navigation
fix(rust): resolve use super::* callees in #[path] modules - #1892
seonghobae wants to merge 1 commit into
Conversation
Map #[path] module inclusions to their declaring parent so bare names imported via `use super::*` resolve through the lexical parent module instead of global same-name matching across workspace crates. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Maintainer note: this PR is still blocked on required review ( |
…ares it (#3064) A Rust module loaded with `#[path = "…"]` was found by its file's directory: fast-mlsirm's `#[path = "../../../tests/unit/scaling_tests.rs"] mod tests;` in `crates/core/src/scaling.rs` made `tests/unit/scaling_tests.rs`'s `use super::*` walk to a `tests/unit` module that doesn't exist, so its `predict_rating_multi(1)` linked to nothing, or to a same-named function of another crate; its `crate::` had no crate, and the parent's private items looked out of its reach. From the declaring side, a path through such a module (`utils::mock_event(…)` under `#[path = "./utils.rs"] mod utils;`) reached nothing. The fix reads each file's `#[path]` declarations as the Rust Reference reads the attribute (from the declaring file's directory, or inside an inline `mod` from that module's own; a path that leaves the project, by escapesRoot, or that a `cfg_attr` sets, names no file): - rustSubmodule: a module the module declares once with a `#[path]` is the file it names, whatever else loads that file too (a helper several tests load is each test's); cfg alternatives that name a file each stay unknown, and a path's 2015 crate-root fallback no longer reaches past such a module to a namesake at the crate root. - rustPathClaim: a file the regular rules don't place is the module of the one `#[path]` declaration that loads it, if exactly one does. Placed (rustPlacedByName) are crate roots, files with a `fn main` or `#![no_main]` of their own (trybuild cases, fuzz targets), and files a plain `mod name;` declares in the module owning their directory or in an inline module of one above it (dioxus's `mod components { pub mod home; }` in main.rs). Only for a file left over are the project's Rust files that write `path =` read (a byte check first), once per resolver. With a claim, rustSuperModule is the declaring module, rustFileModule owns the file's directory (rustc reads every `#[path]` file as a mod.rs), rustCrateRootModule is the declaring file's crate, and rustModuleWithin, isRustItemVisibleFrom and isVisibleAcrossFiles see the file inside the declaring module, so `use super::*` brings in its private items. - rustCrateGraph: `[[example]]`, `[[test]]` and `[[bench]]` paths are target roots, as `[lib]`/`[[bin]]` ones are since PR #3014, and such an example is its own crate's root (dioxus's `examples/07-fullstack/handling_errors.rs`). Validation: - rust-path-super-glob.test.ts (PR 1892's case, credited) and rust-path-attribute-modules.test.ts (7 cases): on main all 8 fail; all pass. Every rust-* suite passes. - A/B against main, native kernel: fast-mlsirm (its Rust files) +2,796 links (1,839 calls, 427 references, 334 constructions, 196 imports), 71 retargeted (exposure_tests.rs's `Lcg::next_f64` from cdm_tests.rs's private `Lcg` to exposure.rs's, the declaring module's helpers instead of bifactor_grm.rs's), 87 reaching the same item through the declaring module (confidence 0.4 to 0.9), 0 removed; dioxus +27 (each headless test's `utils::mock_event(…)` into the helper five tests load); tokio +2 (`use super::AtomicU64` in the files atomic_u64_as_mutex.rs loads); ripgrep, axum, clap, serde, gleam, express and flask unchanged. - Cost, native kernel, medians of 3 interleaved runs: fast-mlsirm CPU 15.3 -> 15.8 s, wall 4.2 -> 5.2 s, peak RSS 825 -> 882 MB; tokio CPU 26.1 -> 26.7 s, wall 10.4 -> 11.2 s, peak RSS 1,023 -> 1,028 MB; dioxus CPU 34.8 -> 35.6 s, wall 10.3 -> 11.2 s, peak RSS 1,125 -> 1,120 MB; gleam CPU 24.1 -> 23.8 s, wall 6.6 -> 6.7 s, peak RSS 1,027 -> 1,023 MB. Builds on PR #1892 by @seonghobae. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thank you for tracking this down, @seonghobae! Your fix for |
Summary
#[path = "..."] mod name;inclusions to their declaring parent module file sosuperin an included file refers to the lexical parent, not a path derived from the included file's disk location (Rust Reference, Modules / Paths).usedeclarations (includinguse super::*globs) into import mappings and resolve bare callees through the imported module before global name-matching.scripts/repro-rust-path-callee.shreproducing CodeGraph: same-name callee over-approximation for scaling test module imports ContextualWisdomLab/fast-mlsirm#1837 (same-namepredict_rating_multiin two crates;#[path]test module withuse super::*must call the parentscaling.rssymbol, not the decoy inlib.rs).Test plan
npx vitest run __tests__/rust-path-super-glob.test.tsnpx vitest run __tests__/rust-self-owner.test.ts(no regression)./scripts/repro-rust-path-callee.shContext
Fixes false callee edge reported in ContextualWisdomLab/fast-mlsirm#1837 where CodeGraph 1.2.0 linked
pr_elom_rowmean→crates/fast-mlsirm-py/src/lib.rs:predict_rating_multiinstead ofcrates/mlsirm-core/src/scaling.rs:predict_rating_multi.Made with Cursor