Remove crate from salsa EditionedFileId#21767
Conversation
86ae3d8 to
b784fb3
Compare
This broke the contract of `HashEqLike`, causing interning to return different IDs
b784fb3 to
d9560f8
Compare
PartialEq impl for EditionedFileIdDataEditionedFileIdData
b33ecf3 to
6d08c43
Compare
6d08c43 to
5abc9af
Compare
EditionedFileIdDataEditionedFileId
|
@Veykril did you measure the memory impact? |
There was a problem hiding this comment.
Pull request overview
This PR refactors EditionedFileId to no longer carry a Crate, and threads crate context explicitly where required (notably item-tree lowering), aiming to fix a regression around span/origin handling in large workspaces (rust-analyzer issue #21721).
Changes:
- Simplify
base_db::EditionedFileIdto wrap onlyspan::EditionedFileIdand remove “guess origin” APIs. - Update item-tree queries/APIs to accept an explicit
Crateparameter and adjust call sites accordingly. - Refresh affected tests/fixtures and golden test outputs to match new IDs/behavior.
Reviewed changes
Copilot reviewed 38 out of 38 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/test-fixture/src/lib.rs | Switch fixture helpers to construct EditionedFileId from span::EditionedFileId without crate guessing. |
| crates/rust-analyzer/src/cli/ssr.rs | Update SSR CLI to use EditionedFileId::current_edition. |
| crates/rust-analyzer/src/cli/analysis_stats.rs | Thread Crate into item-tree calls; adjust source-root iteration. |
| crates/load-cargo/src/lib.rs | Use span_file_id accessors when producing proc-macro span responses. |
| crates/ide/src/view_item_tree.rs | Pass an explicit crate into file_item_tree for debug item-tree rendering. |
| crates/ide/src/typing/on_enter.rs | Replace current_edition_guess_origin usage with current_edition. |
| crates/ide/src/typing.rs | Remove crate-guessing wrapper creation; pick a crate and construct EditionedFileId directly. |
| crates/ide/src/signature_help.rs | Update expected signature-help output ordering. |
| crates/ide/src/references.rs | Update reference-search scope construction to new EditionedFileId API. |
| crates/ide/src/lib.rs | Replace current_edition_guess_origin usage with current_edition in multiple APIs. |
| crates/ide-ssr/src/from_comment.rs | Use current_edition when parsing comment-based SSR patterns. |
| crates/ide-db/src/traits.rs | Update test fixture EditionedFileId construction to from_span_file_id. |
| crates/ide-db/src/test_data/test_symbols_with_imports.txt | Update golden IDs after interned-ID changes. |
| crates/ide-db/src/test_data/test_symbols_exclude_imports.txt | Update golden IDs after interned-ID changes. |
| crates/ide-db/src/test_data/test_symbol_index_collection.txt | Update golden salsa IDs after query/input changes. |
| crates/ide-db/src/test_data/test_doc_alias.txt | Update golden salsa IDs after query/input changes. |
| crates/ide-db/src/search.rs | Construct EditionedFileId without embedding crate context. |
| crates/hir/src/semantics/child_by_source.rs | Adjust derive-macro mapping to obtain a crate without HirFileId::krate. |
| crates/hir/src/semantics.rs | Update edition attachment fallbacks to current_edition and remove crate from EditionedFileId::new. |
| crates/hir/src/lib.rs | Update macro diagnostic span/file-id comparisons to new accessor naming. |
| crates/hir-ty/src/tests/macros.rs | Update cfg-test fixture to use a non-test cfg key. |
| crates/hir-ty/src/tests/incremental.rs | Update incremental event expectations (new shim/query names). |
| crates/hir-expand/src/span_map.rs | Use span_file_id when building real span maps. |
| crates/hir-expand/src/lib.rs | Remove HirFileId::krate helper and adjust edition retrieval. |
| crates/hir-expand/src/db.rs | Resolve spans via from_span_file_id rather than guessing origin crate. |
| crates/hir-expand/src/builtin/fn_macro.rs | Construct EditionedFileId without crate in include/relative-file logic. |
| crates/hir-def/src/nameres/tests/incremental.rs | Update item-tree query call sites to pass db.test_crate(). |
| crates/hir-def/src/nameres/mod_resolution.rs | Drop Crate threading from module-file resolution and adjust EditionedFileId construction. |
| crates/hir-def/src/nameres/collector.rs | Thread crate context into item-tree lowering and adjust tests using test_crate. |
| crates/hir-def/src/macro_expansion_tests/mod.rs | Use db.test_crate() instead of extracting crate from file id. |
| crates/hir-def/src/macro_expansion_tests/mbe.rs | Update golden expansion spans/IDs after interned-ID changes. |
| crates/hir-def/src/item_tree/tests.rs | Pass crate explicitly into file_item_tree in tests. |
| crates/hir-def/src/item_tree/lower.rs | Store crate in lowering context to obtain cfg options without HirFileId::krate. |
| crates/hir-def/src/item_tree.rs | Change tracked item-tree queries to accept Crate; plumb crate through TreeId::item_tree. |
| crates/hir-def/src/expr_store/tests/body/block.rs | Update golden BlockId after interned-ID changes. |
| crates/hir-def/src/db.rs | Change DefDatabase::file_item_tree signature to include Crate. |
| crates/base-db/src/input.rs | Update Crate::root_file_id to construct EditionedFileId without crate. |
| crates/base-db/src/editioned_file_id.rs | Replace custom interned struct (with crate) with a simpler #[salsa::interned] wrapper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| let krate = db | ||
| .relevant_crates(position.file_id) | ||
| .first() | ||
| .map_or(Edition::CURRENT, |crates| crates.data(db).edition); | ||
| // FIXME: We are hitting the database here, if we are unlucky this call might block momentarily | ||
| // causing the editor to feel sluggish! We need to make this bail if it would block too long? | ||
| let editioned_file_id_wrapper = EditionedFileId::from_span_guess_origin( | ||
| db, | ||
| span::EditionedFileId::new(position.file_id, edition), | ||
| ); | ||
| .copied() | ||
| .unwrap_or_else(|| *db.all_crates().first().unwrap()); | ||
| let edition = krate.data(db).edition; | ||
| let editioned_file_id_wrapper = EditionedFileId::new(db, position.file_id, edition); |
There was a problem hiding this comment.
unwrap_or_else(|| *db.all_crates().first().unwrap()) can panic when the crate graph hasn’t been populated yet (e.g., during startup), crashing on-type assists. Consider falling back to Edition::CURRENT (and/or early-return None) when there is no relevant crate, instead of unwrapping all_crates().first().
| let mut item_tree_sw = self.stop_watch(); | ||
| let source_roots = krates | ||
| .iter() | ||
| .cloned() | ||
| .map(|krate| db.file_source_root(krate.root_file(db)).source_root_id(db)) | ||
| .map(|krate| (db.file_source_root(krate.root_file(db)).source_root_id(db), krate)) | ||
| .unique(); | ||
|
|
||
| let mut dep_loc = 0; | ||
| let mut workspace_loc = 0; | ||
| let mut dep_item_trees = 0; | ||
| let mut workspace_item_trees = 0; | ||
|
|
||
| let mut workspace_item_stats = PrettyItemStats::default(); | ||
| let mut dep_item_stats = PrettyItemStats::default(); | ||
|
|
||
| for source_root_id in source_roots { | ||
| for (source_root_id, krate) in source_roots { | ||
| let source_root = db.source_root(source_root_id).source_root(db); |
There was a problem hiding this comment.
source_roots is now deduped with .unique() over (SourceRootId, Crate), which means the same SourceRootId will be visited once per crate (common for workspace roots). This can dramatically increase the amount of work (re-scanning/parsing/item-tree building the same files repeatedly) and skew LOC/item-tree counts. Consider keeping uniqueness by SourceRootId and choosing a representative crate per root (or determining a per-file crate inside the loop via relevant_crates(file_id) as needed).
| @@ -1,305 +1,46 @@ | |||
| //! Defines [`EditionedFileId`], an interned wrapper around [`span::EditionedFileId`] that | |||
| //! is interned (so queries can take it) and remembers its crate. | |||
There was a problem hiding this comment.
The module-level doc comment still claims EditionedFileId “remembers its crate”, but the type no longer stores a crate. Please update this comment to reflect the new semantics (interned wrapper around span::EditionedFileId only).
| //! is interned (so queries can take it) and remembers its crate. | |
| //! is interned (so queries can take it) and stores only the underlying `span::EditionedFileId`. |
Fixes #21721