rust-lang / rust-lang/rust-analyzer

Lazy Workspace/Project Discovery

Open
#17,537 5 comments 14 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-project-model C-Architecture E-medium
Dominant language
Rust
Stars
16.9k
Forks
2.2k
Avg merge
1d 12h
Merged PRs (30d)
72

Description

Few notes:

Anyway! Project discovery should be entirely lazy. This change makes the following easier:

  • Monorepos. Projects are often discovered incrementally as the user navigates around a monorepo and it doesn't make sense to do Cargo-style project discovery at startup.
  • Standalone files, like rustlings. Users would be able to just open a Rust file, and through a rust-analyzer.toml in the rustlings repo, IDE functionality would just work for them.
  • Cargo scripts, which have a similar dynamic to that of rustlings/monorepos but scaled down from the latter.

To make this change happen, the currently eager (that is, they occur on startup/workspace folder change) ProjectManifest::discover_all + cargo metadata-style operations would become lazy, rust-analyzer.workspace.DiscoverCommand-style operations that only happen after startup. This would mean several things:

  • Project discovery/indexing wouldn't start until a user opens a Rust file.
  • cargo_metadata::MetadataCommand::new() would become the default mode for flycheck/src/json_workspace.rs (see this comment. That file would no longer be JSON workspace-specific, but it would also make "project discovery" a first-class concept in rust-analyzer.
  • rust-analyzer.linkedProjects would technically be lazily evaluated, but if any value is set, it would effectively be "eagerly" evaluated.
  • The current "rust-analyzer only searches two directory levels down for a Cargo.toml" behavior can be removed in favor of "run cargo-metadata in the parent of the rust file"-esque behavior, which newer Rust users often struggled with and complained about.

To support this change, I think three things need to happen:

  • https://github.com/rust-lang/rust-analyzer/pull/17246 needs to land.
  • The crate graph should be lifted into a standalone, Salsa database.
    • Salsa's interning infrastructure should be used with the crate data as the "key". This is necessary in order to support different feature flags/versions across projects.
  • A nice performance bonus, the VFS should be able to load all a project's files in a single go.
    • Today, rust-analyzer doesn't have a meaningful distinction between the user-facing "startup" and "steady-state, using-the-IDE" phases. It is always already to incrementaly update and rebuild the crate graph, which it does many times during project loading. I think it is worthwhile to have this distinction because it'd then be possible to load all relevant files in a single turn extremely quickly.
    • This is particularly important on network-backed file systems, like EdenFS. I've observed 180x speedups through some naive usage of Rayon.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading ProjectManifest::discover_all, flycheck/src/json_workspace.rs, and the linked DiscoverCommand pull request to map the current eager discovery paths. Review the related Salsa crate-graph and VFS discussions, then use the monorepo, standalone-file, and Cargo-script cases in the issue as the acceptance scenarios for lazy discovery.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.