Commit Graph
2 Commits
Author SHA1 Message Date
Colby MchenryandClaude Opus 5.5 e2aa5d205d fix(rust): a same-file path's inline module is read from its braces, not its indentation (#2713)
PR #2711 and PR #2702 landed a way each to tell which inline `mod` a
place in a Rust file is in. #2711's isInRustInlineModule scanned lines
upward for `mod <name> {` and trusted rustfmt's indentation to find where
the block closes. #2702's rustModBlocks scans the braces, skipping
strings, raw strings, char literals and comments, and keeps the result in
rustUsesOf. isInRustInlineModule now asks rustBlockAt for the innermost
block around the candidate, as rustDeclaredItems does, so there is one
answer to that question.

What changes:
- An item written without indentation inside `mod flat { … }` is found
  through `flat::Flat`. The indentation rule rejected it.
- `outer::Shell` is only `outer`'s own `Shell`, not one declared in a
  `mod deep` inside it. The upward scan accepted any item below the
  `mod outer {` line.
- A file whose braces don't all close says nothing, as it does for the
  `use` walk of PR #2702.

The A/B (main 818e7803 vs this change; axum, tokio, clap, serde,
ripgrep, gleam, dioxus, and the gin, serilog, flask and express
controls) is byte-identical. rust-path-same-file.test.ts gains the two
cases. The `flat::Flat` one fails on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 18:31:06 +00:00
Colby MchenryandClaude Opus 5.5 505c355be3 fix(rust): a name written through a path is what the path names, not a same-file namesake (#2711)
A Rust name written through a path is an item of what the path names: a
module (`ast::Pattern`, `io::Error`), a type (`Source::Record { … }`) or a
crate (`mio::Interest`, `std::ffi::OsStr`). isRustNameInScope accepted any
candidate in the file the path is written in, whatever the path said, and
a std path only when the candidate was in another file:
- clap's `std::ffi::OsStr` linked to its own `struct OsStr`, and
  `io::Error`, `fmt::Error` and `fmt::Result` in `error/mod.rs` to its own
  `Error` and `Result`;
- tokio's `mio::Interest` linked to its own `Interest`, and
  `std::time::Instant` to its own `Instant`;
- serde's tests' `Token::Struct { … }` literals linked to their own
  `Struct`s, and serde_derive's `syn::Path { … }` to a `Default::Path`
  variant;
- gleam's `ast::Pattern` linked to the `enum Pattern` beside it, and
  `BinaryBuilderPosition::RecordAttribute { … }` to another enum's
  variant of that name.

Fix, in the path branch of isRustNameInScope:
- A path from std, core, alloc or a crate the manifests depend on names
  nothing of the project's, in any file, unless the project is that crate
  or a `use` in the file binds the root.
- The same-file shortcut is gone. A candidate is the path's when its
  file is the path's module, its qualified name holds the segment (a
  type's variant or method), or it sits in an inline `mod` of that name
  in the file (isInRustInlineModule; rustfmt closes the block at the
  indentation it opens at).
- Through a module a `use` binds, a candidate must be in a crate that
  `use`'s path can reach (rustUseCanReach, as for a bare name): tokio's
  `io::Handle` under `use crate::runtime::io` is tokio's own, not
  tokio-test's `io.rs` `Handle` (a dev-dependency).

Tests: rust-path-same-file.test.ts, 6 tests, on both engines; 5 fail
on main (the sixth is the inline-module guard), and the crate-reach one
also fails with only that rule switched off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 17:38:32 +00:00