iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🔖

[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.

Dockerfile
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
docker-compose.yml
version: "3"

services:
  rust-app:
    container_name: "rust-app"
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    volumes:
      - ..:/workspace.rust/src/app
.devcontainer.json
{
    "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:
https://marketplace.visualstudio.com/items?itemName=rust-lang.rust

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.
https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer
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:
https://github.com/rust-analyzer/rust-analyzer/issues/1834

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.

Dockerfile
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
docker-compose.yml
version: "3"

services:
  rust-app:
    container_name: "rust-app"
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    volumes:
      - ..:/workspace.rust
.devcontainer.json
{
    "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...

rust-analyzer responded without any issues.

GitHubで編集を提案

Discussion