iTranslated by AI
[rust-analyzer] Troubleshooting: Rust Auto-completion Not Working in VS Code
Background (Feel free to skip)
Recently, I've had opportunities to work with C-family languages for business. While I understand how to use them, from the perspective of modern programming languages, it might seem like I'm doing things that are extremely tedious, such as wondering if I've released memory or dealing with pointers and pass-by-reference. (Surprisingly, I don't hate it.)
I knew about the existence of Rust, which apparently aims to be an alternative to C and C++, but I had never used it.
Since I'm already handling C-family languages at work to serve as a point of comparison, I thought this would be a great opportunity to try out Rust and see how superior it really is. That's what triggered me to touch Rust this time.
Main Subject
I don't like cluttering my PC environment by installing various compilers and such directly.
Basically, I do most of my playing around by building environments inside Docker.
Building an environment with Docker itself isn't a big deal (when doing it at home).
I built an environment where I could execute Rust in no time using the following configuration.
FROM rust:1.48-buster
RUN apt-get update && apt-get install git
RUN cargo install cargo-edit #← Better to include this beforehand, it's quite heavy
version: "3"
services:
rust-app:
container_name: "rust-app"
build:
context: .
dockerfile: Dockerfile
tty: true
volumes:
- ..:/workspace.rust/src/app
{
"name": "Learning Rust",
"dockerComposeFile": "docker-compose.yml",
"service": "rust-app",
"workspaceFolder": "/workspace.rust",
// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}",
},
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-azuretools.vscode-docker",
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "docker --version",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
}
Now, with just this, I can connect to the container using Remote-Containers and play with Rust.
However, I still want a Rust extension...
It's a bit tough without autocompletion.
Initially, I selected the following extension:
With this, autocompletion works, and I can see the documentation by hovering over things. It's a huge help!
...or so I thought at one point.
It barely works
It wouldn't autocomplete at all, and for some reason, even after installing external crates with cargo add xxxx, the autocompletion wouldn't respond. In fact, it couldn't even load them despite being installed.
It would load if I reopened the container (using the Remote-Containers: Reopen command), but it's a hassle to do that every single time.
Reading the extension description carefully, I found the following explanation:
This extension is deliberately conservative about snippets and doesn't include too many. If you want more, check out Trusty Rusty Snippets.
It seems it's not very well-suited for autocompletion.
So, I thought about looking for another extension, but another language server was already introduced in the site's description.
Rust support is powered by a separate language server - either by the official Rust Language Server (RLS) or rust-analyzer, depending on the user's preference. If you don't have it installed, the extension will install it for you (with permission).
Apparently, there's something called rust-analyzer as well.
Still doesn't work
I immediately installed rust-analyzer as an extension. As you can see from the version, it's a language server still under development, but it's said to have more robust autocompletion than RLS.
However, it still won't work.
In fact, it started throwing errors.
rust-analyzer failed to discover workspace
Can't find the workspace...?
Investigating the cause
The folder structure when I introduced rust-analyzer was something like this.
A single workspace contains multiple projects.
And the workspace should certainly exist.
In .devcontainer.json, it's explicitly specified as /workspace.rust.
What could be wrong?
workspace.rust/
└src/
└app/
├sample1/
│ ├src/
│ │ └main.rs
│ └Cargo.toml
├sample2/
│ ├src/
│ │ └main.rs
│ └Cargo.toml
├sample3/
│ ├src/
│ │ └main.rs
│ └Cargo.toml
└sample4/
├src/
│ └main.rs
└Cargo.toml
Cause
To get straight to the point, the cause was that multiple projects existed within a single workspace.
Here is a link to the GitHub Issue where the cause was identified:
At this stage, it seems it won't work unless it's a single project in a single workspace.
However, it appears that preparations for multiple support are being made, but it hasn't been implemented yet because validation is still insufficient.
Fix & Improvement
As a result, the configuration became like this.
FROM rust:1.48-buster
RUN apt-get update && apt-get install git
RUN rustup component add rust-src # Newly added, required for rust-analyzer
RUN cargo install cargo-edit #← Better to include this beforehand, it's quite heavy
version: "3"
services:
rust-app:
container_name: "rust-app"
build:
context: .
dockerfile: Dockerfile
tty: true
volumes:
- ..:/workspace.rust
{
"name": "Learning Rust",
"dockerComposeFile": "docker-compose.yml",
"service": "rust-app",
"workspaceFolder": "/workspace.rust",
// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}",
},
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-azuretools.vscode-docker",
/// Set up rust-analyzer ///
"matklad.rust-analyzer",
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "docker --version",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
}
Additionally, I modified the folder structure to a simpler form.
workspace.rust/
└sample1/
├src/
│ └main.rs
└Cargo.toml
When I rebuilt the container and connected to it...
Discussion