July 1, 2022·4 min read·engineeringrusttoolingeditorsarchitecture

RLS deprecation reflects the latency requirements of an editor

Rust's tooling team recommends rust-analyzer as RLS enters deprecation. The architectural reason is the difference between completed compiler analysis and incremental answers needed while code is changing.

An editor needs an answer before the programmer has finished writing a valid program. Reusing compiler analysis is attractive for accuracy, but producing a completed analysis before answering a local question can impose the wrong latency on interactive work. That tension explains the transition from RLS to rust-analyzer more clearly than a comparison of feature lists.

The 1 July deprecation announcement tells RLS users to migrate to rust-analyzer. Builds will continue until at least the planned Rust 1.64 release on 22 September, with the timeline subject to change. The decision follows the earlier adoption of rust-analyzer as the intended replacement through RFC 2912.

I am impressed by Rust's semantics, and the editor has a substantial role in making those semantics usable while code is being changed. A correct answer that arrives after the programmer has moved elsewhere has limited interactive value. Responsiveness matters most when it remains connected to a meaningful account of the source.

Compiler reuse had a specific tradeoff

The rust-analyzer adoption RFC, begun in April 2020, explains the architectural difference. RLS consumes save-analysis information produced by rustc after compilation. Reusing the compiler helps keep the analysis aligned with the language, but generating that information is expensive for interactions such as completion.

Rust-analyzer instead follows an incremental, on-demand approach. A request can obtain the information it needs without treating the entire compilation as a prerequisite. The RFC describes that architecture as related to the direction in which the compiler itself has been evolving.

That changes the unit of work. A completion request is about a source location and the information relevant to that location. A batch compiler must establish much more about a crate before producing an artifact. Sharing the language does not make the two requests identical computational problems.

The distinction also explains why a new implementation can be worthwhile despite duplication. Reusing code is valuable when the reused component has a suitable interface and lifetime. If obtaining its result requires the wrong amount of work before each interaction, reuse can preserve accuracy at an unacceptable cost to responsiveness.

The original RLS design recognized incomplete programs

The original RLS proposal already identifies rapid feedback and incomplete source as requirements. It describes a long-running service with a database and work queue, receiving compilation requests and answering queries. The concern was present in the original problem statement.

That proposal discusses improvements through lazy compilation and retaining compiler state in memory. It also explains the difficulties of cancellation and invalidating computed state when new edits arrive. Killing a batch process releases its data, while a persistent process must leave its internal structures consistent for the next request.

This history prevents an inaccurate account in which RLS simply ignored the needs of editors. The project recognized those needs and proposed ways to address them through compiler integration. The later transition reflects experience with the resulting architecture and a different implementation approach.

My preference is to read a replacement decision against those original requirements. A useful architectural explanation identifies which constraints became difficult to satisfy. Describing the older tool as merely obsolete says little about what the replacement needs to do differently.

A persistent service has different memory needs

RFC 2912 gives memory management as another example of the difference between compilation and an editor. A compiler can intern types for a compilation and release them together when the operation ends. A long-running editor service cannot assume that all accumulated state will become irrelevant at that same boundary.

The RFC also discusses query dependencies. A batch compilation may stream dependency information to disk for a later invocation. An editor needs that information again when the next edit arrives. A storage decision that suits the batch lifetime can therefore add unnecessary work to the interactive one.

The proposed long-term direction is shared libraries used differently by the two host processes. This is a goal for reducing duplicated language implementation while permitting distinct memory and query strategies. It should not be described as a completed merger of rustc and rust-analyzer on the announcement date.

That distinction matters because independent implementation has its own maintenance cost. The RFC names duplication and possible lag behind language changes as drawbacks. Adopting rust-analyzer chooses a direction for tooling effort without claiming that all architectural differences have already been resolved.

The RFC also distinguishes the core protocol from negotiated extensions. Features beyond the shared protocol need coordination between client and server. A replacement can therefore use the same protocol while still requiring editor-specific integration for capabilities that the core interface does not describe.

The migration changes the server behind the editor

The deprecation announcement describes RLS as a Language Server Protocol implementation. Editors use that protocol to request language-specific information. Rust-analyzer supplies another implementation, so the transition can preserve the editor while changing the service that answers its requests.

For VS Code, the announcement directs users to uninstall rust-lang.rust and install rust-lang.rust-analyzer. Other editors have their own installation arrangements. The package identity matters because installing a replacement server without changing which extension starts it may leave the original tool active.

The team also plans deprecation notifications and, after regular RLS builds end, a small replacement executable that tells users RLS is unavailable. Those are announced migration measures. On 1 July they remain plans, and the release timeline explicitly allows adjustment if problems arise.

This makes the transition an operational change in the development environment. The editor client, selected server and installation method all contribute to what the user experiences. An installed binary alone does not establish that a particular workspace is using it.

I regard the architectural explanation as the useful part of this deprecation. Rust-analyzer organizes analysis around questions asked during editing, while the project also aims to share more language implementation with rustc. The transition concentrates tooling work on that approach and gives existing users a defined path to the new server.