rust-lang / rust-lang/rust-analyzer
scip: panics with "Invariant violation: file emitted multiple times" when one file is mounted into two targets via #[path]
@moosama76 is already working on this.
Since Sep 8, 2026.
- Dominant language
- Rust
- Stars
- 16.9k
- Forks
- 2.2k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 72
Description
rust-analyzer scip panics on any workspace where a single source file is reachable from more than one target via #[path]. This is a legal and reasonably common pattern for sharing helpers between integration-test targets, and it makes SCIP indexing impossible for the whole workspace.
Version
rust-analyzer 1.93.0 (254b5960 2026-01-19)
rustc 1.93.0 (254b59607 2026-01-19)
aarch64-apple-darwin
Minimal reproduction
Six files:
Cargo.toml
src/lib.rs
tests/shared/helper.rs
tests/target_a.rs
tests/target_b.rs
Cargo.toml
[package]
name = "scip-path-repro"
version = "0.1.0"
edition = "2021"
src/lib.rs
pub fn hello() -> u32 { 42 }
tests/shared/helper.rs
pub fn helper() -> u32 { 1 }
tests/target_a.rs and tests/target_b.rs — identical, both mounting the same file:
#[path = "shared"]
mod shared {
#[path = "helper.rs"]
pub mod helper;
}
#[test]
fn t() { assert_eq!(shared::helper::helper(), 1); }
Then:
$ rust-analyzer scip . --output out.scip
thread 'main' panicked at src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs:227:17:
Invariant violation: file emitted multiple times.
Exit 101, no index written.
Expected
tests/shared/helper.rs is one file that legitimately belongs to two crate targets. SCIP should emit it once (or once per target with distinct document identity), rather than panicking.
Notes
- Reproduces with and without
--exclude-vendored-libraries. - On the real workspace this was found in (single crate, 9
[[bin]], 20 examples, several integration-test targets) the panic arrives after ~115s and ~7.8 GB peak RSS, so on a large project the cost of discovering it is significant. cargo testbuilds and runs both targets without complaint — only the SCIP writer objects.- The pattern is deliberate in that codebase: a second test target re-mounts a module tree verbatim via
#[path]to run the same tests under a different global allocator.
Happy to test a patch.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.