Fantastic project btw, and it couldn't come at a better time. With the way prices are going I really hope people start paying attention to memory again.
Several things here: 1. We don't need all the information (project can have 1000+ dependencies, while query might only care about the current open file), so the amount of information we load is smaller. 2. Most of the time IDE does not actually do any queries, so if you switch to browser/Slack, you don't pay the tax. 3. Since data is loaded to the disk, after initial indexing restarting no longer consumes that much ram, and you get reindexing for free. 4. Besides offloading, I implement quite a bit of memory optimizations (some of which are covered in docs: https://rust-glancer.github.io/docs/development/MEMORY.html ), so it's a combination of factors.
In some sense I feel like that example is the canonical "you need a full picture of the world" case, to the point that it's probably worth special casing _just_ that, and using local analysis for everything... but it seems hard to avoid that pain on any typo for example
Inversely... do you have a ballpark for what the size of the on-disk structures end up being? Not that it matters _that_ much but Rust projects already have a tendancy to be disk hogs during development
As for the size -- the Rust Glancer artifacts for Rust Glancer itself currently take 225mb. And that's proportial to the project size only, e.g. it doesn't grow over time on its own.
// Crate indirect_dep:
pub struct Foo;
// Crate direct_dep:
extern crate indirect_dep;
pub use indirect_dep::*;
// Crate my_crate:
use direct_dep::$0;
($0 denotes the cursor). You cannot know what to complete without analyzing `indirect_dep`. Add macros to the mix and you're going to get a nightmare (yes, name resolution in Rust is a nightmare).In fact, you sometimes need to do type inference inside bodies to infer other bodies, because auto traits propagate across opaques. You might say this does not matter because it only matters for diagnostics... But it does not. It can matter for method resolution.
In general, I'm fairly sure that it is just impossible to build a 100% correct analyzer for Rust code without a query system like rustc's (it can be stored on disk, that's a different story). You can go pretty far without - and this will be enough for some people for an IDE! - but not all the way.
In the comparison table, you indicate indexing times. Could you also measure memory usage, since that's the stated goal of the project?
The difference, however, is that with Rust Glancer you don’t need full reindexing often, so it probably compensates for that to a degree.
But importantly it’s not reindexing the entire project, which is the expensive operation. So you have higher peak RAM when opening a brand new project, but much lower RAM usage while working on the project.
And note that on dirty buffers Rust Glancer doesn't do reindexing at all: it reuses the last available analysis, plus it does syntax-based shallow overlay that is sufficient to be useful but doesn't necessarily detect semantic changes. It's a tradeoff, but this tradeoff makes Rust Glancer competitive in terms of latency with rust-analyzer without compromising RAM and while keeping your CPU cool.
> it completely reindexes the single file that’s saved
This is true, though I have to mention that change in the file might invalidate its reverse dependencies, which can make the partial analysis bigger than just one file/crate, but it's still very fast in practice.
This is when you do full reindexing.
> Is that only an incremental indexing with normally low RAM usage?
Yup, on save you only update the crates that were invalidated.
Both the "user configuration" and the library are configuration masquerading as code. One is dynamically evaluated, the other compiled.
I just figure users of Zed know this... so what are we pretending to talk about?
With things like trait solving I am not reinventing the wheel, and use official tooling (Chalk). Even though now the new solver is recommended, Chalk still does its job and lets me not to worry about potentially the most complex part of the machinery.
In places that seem to be underdocumented, it's always possible to: 1) look into sysroot implementation for clues 2) look into compiler sources 3) hijack stuff from rust-analyzer
I am lucky to not be the first guy who does a Rust LSP, so it's not that fundamental of a research, and much more of just an implementation :)