Rust-Analyzer Architecture
github.com
github.com
Rust being a terse language with generics and macros, sometimes figuring out what type an object is is hard and can easily get lost. Rust analyzer + vscode instantly gives context visually in all my code and even names types better than when the compiler errors at you when you get it wrong. This is especially true when dealing with a lot of async rust and you need to know the exact fully declared type of an object so you can fully decl it's type for a pin/box to pass around. Game changer. Being able to use to jump to definition is a huge win. I can walk code so much easier now and understand issues without a lot of mental energy or digging. It also updates in realtime as I code.
Big productivity boost I know for a lot of devs on Fuchsia. It would take me at least twice as long to get up with a new crate and be productive with it. The same is true as my own code base grows and I can't keep it all in my memory and remember. Impossible to stay as productive as code grows in rust without something like this anymore.
Also a huge win for the fact that it works remotely with vscode's remote features so I can have my code + rust-analyzer on my big linux machine remotely but still edit that code and get the context locally on my dinky/slower/older macbook.
My only wish is that it eventually gains some of the deeper refactoring features in vscode you can still get in Rust + Clion/JetBrains. Almost there.
0: https://github.com/microsoft/language-server-protocol/issues...
If anyone knows how to turn this off in vim/ale, I'd appreciate it.
[0]: https://github.com/neovim/neovim [1]: https://neovim.io/doc/user/lsp.html
0: https://github.com/rust-analyzer/rust-analyzer/issues/4224
There are two popular emacs packages for rust-analyzer: lsp[0] and eglot[1]. lsp (language server protocol) package is the default for racer. Eglot has far more features and is correspondingly resource hungry.
Detailed type information has a super helpful impact on my ability to review Rust code in general. I find reviewing rust code much more productive when I can see what owns a variable, how long it lives, and how it's being used (immutable vs mutable). So yea, lsp or eglot. Super helpful.
[0] https://emacs-lsp.github.io/lsp-mode/ [1] https://github.com/joaotavora/eglot
It's not bothering me that much that I'd find a solution, because I don't need the help of analyzer in crates that I maintain anymore...
It's 99% reliable.
I guess a consequence of dark mode is you should not use transparency in your diagrams if you have black lines.
Not only is it infinitely better than the default RLS, it's honestly one of the better IDE experiences I've ever had in any language period. In particular it has novel features like inline labels for inferred types, argument names when calling functions, etc.
The internal architecture (or rather culture) of making the thing easy to work with is also an important factor. For example, this very document is a part of intentional “architecture for ease of development”.
The fancier stuff like incremental compilation with salsa are liabilities: Rust is a complex language, so we have to pull complex tricks to make IDE works. This slows development down, so we compensate by focusing even more on build time, isolating complexity, and reducing interdependencies.
Edit: Not sure why you're getting downvoted for making a positive, relevant, and factual statement. Sometimes I just can't figure out what goes on in people's heads when they downvote something.
Personally I'd have preferred more community investment in an IDEA plugin.
At the same time, there’s quite a bit of synergy if you go in the other direction, and provide a unified language specific tooling, especially for languages for which it is meaningful to self-host.
It’s sort-of like an expression problem: no matter how you slice it, there’s NxM cells to fill.
Ideally, one should have both. Incidentally, Rust has both :)
It’s also instructive to compare with LLVM: backhands is where all the languages are the same, frontends is where all the languages are different. It’s pretty hard to invent a “frontend IR”, which doesn’t make all the languages feel the same.
It’d have been much more useful to build bindings for IDEA plugins so they could be integrated into arbitrary editors, especially as the IDEA plugins for most languages even after several years of LSP development are still superior.
All in all it’s like the whole JVM vs. WASM, Java vs Electron story again, with someone deciding to reinvent the wheel but worse.
There’s even bindings like https://github.com/Ruin0x11/intellij-lsp-server or https://plugins.jetbrains.com/plugin/10209-lsp-support to glue it all back together.
It’d have been much simpler to reuse an existing ecosystem from the start.
Language servers are just that: servers, exposing a very unopinionated API. They run in a separate process, can be written in any language, and can even be hosted from any machine. That makes for a much more open and flexible standard.
Then VSCode could've immediately had all the advantages of IDEA, and we'd be able to use both interchangeably.
If what you're suggesting is an LSP that wraps any given IDEA plugin and maps it to the LSP protocol, well, that can still be done (assuming it could ever be done) and would've still required the LSP protocol to be invented first.
On top of all that: you're welcome to re-use any code out there (in any language!) when writing an LSP. Nothing stops you from leveraging the bulk of an IDEA plugin, or whatever generic compiler utilities go into IDEA, when making your own LSP. I wouldn't say any work is wasted at all.
Which are mostly collections of dozens of languages and dozens of backends reusing the same functionality in compiler collections like the GCC or LLVM.
Instead, with LSP, every single one reimplements everything from scratch.
And the features available to you differ heavily from one language to another.
Still not sure where you're getting this idea that everything has to be done over from scratch. Code sharing is code sharing; the only new thing that fundamentally has to be written is the mapping to a particular public interface, but that had to be done anyway because no previous interface was generic enough to be used by all possible editors.
As an example: the original RLS mostly just uses Rust's existing compiler internals. It doesn't perform super well, because rustc is optimized for full-build usecases and not interactive/partial usecases. But it didn't have to be written in a clean-room environment just because it's exposing a new API to the outside world.
The significant task in a language server isn't the "parse and show types" part but the "provide resharper-like refactoring functionality".
And every single language server has to reimplement all these from scratch.
And every single language server ends up with slightly different refactoring functionality, no standardisation or anything.
Compare that to IDEA, where changing the type of a function at one point, and propagating that change to all calling functions across the whole code base is a single key stroke — and always the same, no matter which language you use.
That's what I'm complaining about.
LSP is an improvement for editors, but significantly worse than the alternative for actual IDEs.
This is mostly true about IDEA as well. Take a look at the extractFunction implementation from IntelliJ Rust:
https://github.com/intellij-rust/intellij-rust/tree/6b2c4dfa...
It is based on a generic `RefactoringActionHandler`, and not on the specialized `ExtractFunctionActionHandler`.
There's relatively little code sharing you can do for high-level things in IDEs.
The use interface sharing is another thing, and that is exactly what LSP achieves: it standardizes common actions across many languages.
Personally I hate using IDEA because it's too sluggish for my taste. With language servers I can pick whichever IDE I want (which for me means VSCode, which is about as snappy as it gets outside of text-mode editors) and still have rich language integration.
I have been making a strong push to move to 100% Vim for development, but those inline annotations in VSCode with rust analyzer are amazing, especially while I'm still learning Rust.
I'm currently using YouCompleteMe with rust-analyzer, plus rust-vim for autoformatting
[0]: https://github.com/neovim/neovim [1]: https://neovim.io/doc/user/lsp.html [2]: https://github.com/neovim/nvim-lspconfig
I use the Vim extension in VSCode for editing with my vim muscle memory, even though it has occasional snags/surprises
I was doing Rust in VSCode and liked it but the Python support in VSCode was pretty terrible, and Go was so-so (Refactor/Rename tends to rename about 50% of the occurrences if you're lucky), so I wanted to try to concentrate everything in one editor.
The downside for a language like Python without strong type system is the need to use the debugger super often, and I haven't gotten my command-line debugging chops up yet. The IntelliJ debugging experience is really, really nice.
So RA can get close to the trait resolution of the compiler, which is probably the most challenging part. I haven't used Intellij in a while, but I doubt they can ever get close with their custom implementation. I always had trouble with trait resolution/autocompletion, which is often where you need from the IDE the most.
I've given up and I've been using the IntelliJ Rust plugin, which just works.
I don't know what the Rust Analyzer and RLS teams are doing wrong, maybe it's insufficient QA or something, but it's a huge turnoff when after repeated attempts over a year I've experienced nothing but failure after failure.
And of course if you want to keep using IntelliJ, that's an awesome tool as well.