Meta(
    title: "Finally rust-analyzer is available via Rustup (sort of)",
    summary: None,
    published: Some(Time(
        year: 2023,
        month: 4,
        day: 29,
        hour: 23,
        minute: 23,
        second: 4,
    )),
    tags: [
        "rust",
        "programming",
    ],
)
---
A while back the Rust project switched from recommending the Rust Language Server (rls) to officially supporting it's replacement, rust-analyzer for use in IDE's and editors. There were solid technical reasons for the change, but the rollout was not without some growing pains.

One issue with using an lsp server in the context of Rust is that it is common for people to have multiple versions of the Rust toolchain on their system. Most people who use Rust in anger have at least a stable toolchain and a nightly, while some projects (such as the Linux kernel) requiring a specific stable compiler version. It's not a problem due to the language changing that fast (although a few years ago it would have been). The issue is that in order to support procedural macros rust-analyzer must be built from the same source as the compiler in use. That means that one would need a version of the program for each toolchain, and a way to switch between them.

This is automagically taken care of already if you're using VSCode, as it maintains it's own version of the rust-analyzer binary. But I suspect there's actually a rather large minority (myself included) who use Vim, Neovim, Helix or possibly even Emacs. For NeoVim, Vim and Helix the config must point to an actual binary.

Up until today I was just rebuilding the rust-analyzer source myself every time I updated my toolchains. But that meant that switching from a project that used to stable compiler to one using the nightly compiler left me out in the cold with respect to getting all of the available feedback in my editor.

This seems like the sort of thing that we have Rustup for, and indeed the latest version of Rustup allows installing rust-analyzer as an additional component. I was thrilled to find out that rustup was finally providing this feature. However, the binary is not installed into ${HOME}/.cargo/bin like cargo and rustc. Instead, they are putting it in ${HOME}/.rustup/toolchains/${VERSION}/bin where VERSION is the version of the toolchain in use. I'm not sure I understand the reasoning for this decision, but there it is. The devs did provide a way to run the language server by using rustup itself as a proxy, however. This gets us *almost* there. The command looks something like this:

```
rustup run stable-x86_64-unknown-linux-musl rust-analyzer
```
If one was using the nightly compiler, then 'stable' would be replaced with 'nightly', and if one is on a Glibc based distro (I'm on Void) then 'musl' would be replaced with 'gnu'. Anyway, that's cool and all, but we need a way to switch when we switch compilers. So I just made a little wrapper script and placed it into ${HOME}/bin.
```
#!/bin/sh
exec rustup run $(rustup show active-toolchain | awk '{ print $1 }') rust-analyzer $@
```

Now, granted, if you're using an editor like Vim or NeoVim you're probably not a complete noob and can figure things out yourself, but this does seem like adding extra friction to something that could have been fully automated. It's also one more thing to maintain myself. I hope that sometime in the future I'll be able to delete the wrapper script and just move seemlessly from one toolchain to another.