2019-11-18 IDE 团队会议

2019 年 12 月 4 日 · Aleksey Kladov, Igor Matuszewski 代表 IDE 团队

会议由 nikomatsakis 主持。会议记录由 nikomatsakis 编写。与会者:nikomatsakis, pnkfelix, Xanewok, matklad 笔记

Rust IDE

在上一次编译器/IDE 团队会议中,我们讨论了 Rust 中 IDE 支持的总体方向。

目前,作为 Rust 项目一部分开发的两个 IDE 是 Rust 语言服务器(RLS)和 rust-analyzer。前者目前随 Rust 发行版一起发布,而后者则作为“RLS 2.0”工作组的基础。

不幸的是,这两个项目是在没有太多代码共享的情况下独立开发的。我们希望改变这种情况,并找出如何统一这些努力。因此,我们进行了一系列会谈,旨在详细阐述设计空间,并为如何改进未来的情况制定提案。

这篇博客文章简要概述了我们最近的会议。

为什么要有 2 个 IDE?

rust-analyzer 的主要优点是更高的性能(因为完全懒加载的编译模型)和更丰富的功能集(由于更灵活的分析 API)。RLS 的主要优点是精度(它在底层使用 rustc)。此外,RLS 是保存分析基础设施的主要消费者,这非常适合需要代码库静态视图的工具,例如 cargo-srclsif

保存分析

什么是“保存分析”?它是一种不稳定的格式,rustc 用它来记录有关编译代码的信息。它包含相当高级的信息。例如,对于源代码 crate 中的每个标识符,保存分析器会将此标识符映射到定义和用法列表。env RUSTFLAGS="-Zunstable-options -Zsave-analysis" cargo check 可用于指示 rustc 生成保存分析文件(JSON 格式)。由于保存分析是直接从 rustc 内部数据结构生成的,因此保证是正确的(除了 rustc 本身中的错误)。

查询模型

保存分析的根本问题在于,它是针对整个 crate 一次性计算的。这对于非平凡的 crate 来说非常慢,而且也很浪费。在任何给定时刻,实际上只需要一小部分分析信息。rust-analyzer 通过使用 salsa 查询进行代码分析来解决这个问题。结果是一个完全懒加载的整个 crate 图的编译模型。该模型类似于 rustc 内部使用的模型,但在“垂直”和“水平”方向上都更加懒加载。在垂直方向上,rustc 仅在解析和宏扩展之后才开始增量编译;rust-analyzer 在每个文件的基础上进行增量编译。在水平方向上,rustc 一次编译一个 crate;rust-analyzer 将查询用于整个 crate 图。

前进方向

我们目前的假设是,有可能整合这两种方法,而不会使工程工作量翻倍。具体来说,我们将向 rust-analyzer 添加一个选项,以使用保存分析来实现查找用法和重命名功能。这样,我们将获得最重要查询的精确结果,而不会减慢补全速度。但是,与 RLS 不同,rust-analyzer 将不会链接到 rustc,而是依赖 cargo 来运行编译器并生成保存分析数据。如果这种方法有效,我们将考虑冻结 RLS 并完全专注于 rust-analyzer。从长远来看,计划是统一保存分析回退路径和懒加载分析。

在并行进行 RLS/rust-analyzer 统一工作的同时,我们继续推进 rustc 库化,重点关注特征求解(通过 chalk)和类型推断。“库化”是我们一直用来指代将代码从 rustc 中提取到可重用库中的过程,这些库可以由 rustc 和 rust-analyzer 共享。目标是通过库化逐步减少 rustc 和 rust-analyzer 之间重复的代码量,最终目标是拥有一个单一的代码库,或者拥有绝大多数共享的逻辑。