rust-lang / rust-lang/rust-analyzer
crate def map invalidation in `bevy_reflect/src/lib.rs` makes r-a crawl
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 16.9k
- Forks
- 2.2k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 72
Description
rust-analyzer version: I built a version of rust-analyzer atop of 87940a99.
rustc version: rustc 1.90.0-nightly (f26e58023 2025-06-30)
editor or extension: Zed
relevant settings: N/A
repository link (if public, optional): Try to expand any of the imports in Bevy: https://github.com/bevyengine/bevy/blob/2d02f629b38ce062689e7b18415b6d8746886507/crates/bevy_reflect/src/lib.rs#L641
@workingjubilee brought this up the other day. I was able to reproduce this by expanding Glob imports in Bevy, and saw slow performance even after cache priming completed. I thought this was strange, as cache priming should should fill out the nameres caches. It did, but RA_PROFILE, strangely, showed diagnostics and especially trait solving occurring this assist:
10635ms handle_code_action
10608ms semantic_diagnostics
10580ms diagnostics @ name = None
10578ms diagnostics @ name = Some(Name { symbol: "impls", ctx: () }) (4 calls)
7926ms diagnostics @ name = Some(Name { symbol: "alloc_utils", ctx: () }) (226 calls)
7768ms diagnostics @ name = None (164 calls)
410ms borrowck_query (1998 calls)
371ms mir_body_query @ detail = "[missing name]" (1998 calls)
315ms trait_solve_query @ detail = "Copy" (4015 calls)
304ms solve @ krate = Crate(Id(4000)) block = None (4015 calls)
473ms diagnostics @ name = None (335 calls)
210ms infer_query (368 calls)
2820ms infer_query (1999 calls)
132ms iterate_method_candidates_dyn @ mode = Path name = Some(Name { symbol: "new", ctx: () }) traits_in_scope_len = 67 (978 calls)
108ms iterate_method_candidates_with_autoref @ name = Some(Name { symbol: "take", ctx: () }) (555 calls)
107ms iterate_method_candidates_by_receiver @ name = Some(Name { symbol: "take", ctx: () }) (971 calls)
107ms run_in_snapshot (1387 calls)
828ms resolve_obligations_as_possible (135150 calls)
723ms trait_solve_query @ detail = "FromResidual" (4800 calls)
711ms solve @ krate = Crate(Id(4000)) block = None (4682 calls)
1610ms trait_solve_query @ detail = "CoerceUnsized" (8496 calls)
1590ms solve @ krate = Crate(Id(4000)) block = Some(BlockId(262a5)) (8369 calls)
2105ms infer_query (27 calls)
128ms iterate_method_candidates_dyn @ mode = MethodCall name = Some(Name { symbol: "register", ctx: () }) traits_in_scope_len = 34 (234 calls)
106ms iterate_method_candidates_with_autoref @ name = Some(Name { symbol: "register", ctx: () }) (187 calls)
106ms iterate_method_candidates_by_receiver @ name = Some(Name { symbol: "register", ctx: () }) (360 calls)
106ms run_in_snapshot (609 calls)
1881ms trait_solve_query @ detail = "CoerceUnsized" (532 calls)
1881ms solve @ krate = Crate(Id(4000)) block = None (530 calls)
1783ms trait_impls_in_deps_query @ krate = Crate(Id(4000))
1783ms trait_impls_in_crate_query @ krate = Crate(Id(4027)) (98 calls)
198ms body_with_source_map_query (642 calls)
519ms parse @ file_id = EditionedFileId { editioned_file_id: EditionedFileId(8346, Edition2021) } (1135 calls)
517ms SourceFile::parse (1135 calls)
516ms parse_text (1135 calls)
183ms TopEntryPoint::parse @ self = SourceFile (1135 calls)
214ms build_tree (1135 calls)
507ms parse_macro_expansion (12554 calls)
251ms macro_expand (12554 calls)
10221ms handle_code_action
10197ms semantic_diagnostics
10169ms diagnostics @ name = None
10169ms diagnostics @ name = Some(Name { symbol: "impls", ctx: () }) (4 calls)
7926ms diagnostics @ name = Some(Name { symbol: "alloc_utils", ctx: () }) (226 calls)
7768ms diagnostics @ name = None (164 calls)
437ms borrowck_query (2619 calls)
385ms mir_body_query @ detail = "get_type_registration" (2619 calls)
312ms trait_solve_query @ detail = "Copy" (5135 calls)
299ms solve @ krate = Crate(Id(4000)) block = None (5135 calls)
473ms diagnostics @ name = None (335 calls)
161ms infer_query (412 calls)
3412ms infer_query (2618 calls)
184ms iterate_method_candidates_dyn @ mode = Path name = Some(Name { symbol: "of", ctx: () }) traits_in_scope_len = 67 (1401 calls)
153ms iterate_method_candidates_with_autoref @ name = Some(Name { symbol: "insert", ctx: () }) (847 calls)
152ms iterate_method_candidates_by_receiver @ name = Some(Name { symbol: "insert", ctx: () }) (1454 calls)
151ms run_in_snapshot (2061 calls)
111ms iterate_trait_method_candidates @ name = Some(Name { symbol: "insert", ctx: () }) (860 calls)
1018ms resolve_obligations_as_possible (207070 calls)
838ms trait_solve_query @ detail = "FromType" (6562 calls)
820ms solve @ krate = Crate(Id(4000)) block = None (6403 calls)
1858ms trait_solve_query @ detail = "Reflect" (11049 calls)
1831ms solve @ krate = Crate(Id(4000)) block = None (10882 calls)
466ms infer_query (36 calls)
195ms iterate_method_candidates_dyn @ mode = MethodCall name = Some(Name { symbol: "get_field", ctx: () }) traits_in_scope_len = 67 (546 calls)
133ms iterate_method_candidates_with_autoref @ name = Some(Name { symbol: "get_field", ctx: () }) (403 calls)
132ms iterate_method_candidates_by_receiver @ name = Some(Name { symbol: "get_field", ctx: () }) (601 calls)
132ms run_in_snapshot (868 calls)
114ms iterate_trait_method_candidates @ name = Some(Name { symbol: "get_field", ctx: () }) (431 calls)
186ms trait_solve_query @ detail
I initially thought this was a contented lock, but as it turns out, https://github.com/rust-lang/rust-analyzer/pull/19935 forces diagnostics to be run for any code action. Since Bevy has a large of glob imports (and therefore, a large amount of code to compute diagnostics for...) the slowness now makes sense. I don't think we should revert Chayim's changes, but I think we should try to get the new trait solver rolled out ASAP + add some parallelism to trait solving here.
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.
Research direction
Reproduce the slowdown by expanding imports in Bevy's bevy_reflect/src/lib.rs and capture RA_PROFILE output. Start with crate definition-map invalidation, semantic_diagnostics, and trait-solving paths, then compare the behavior introduced by pull request 19935. Done means the code action no longer causes the reported crawl while preserving diagnostics behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- performance
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100