会议由 nikomatsakis 主持。会议记录由 nikomatsakis 撰写。参会人员:nikomatsakis, pnkfelix, Xanewok, matklad 笔记
Rust IDE
在上次编译器/IDE 团队会议中,我们讨论了 Rust IDE 支持的总体方向。
目前,作为 Rust 项目一部分开发的两个 IDE 是 Rust Language Server (RLS) 和 rust-analyzer。前者目前随 Rust 发行版一同发布,而后者则作为“RLS 2.0”工作组的基础。
不幸的是,这两者目前各自独立开发,代码共享很少。我们希望改变这种状况,并找出如何统一这些工作的方法。因此,我们进行了一系列讨论,旨在阐述设计空间,并为如何改进未来的状况制定提案。
这篇博客文章简要总结了我们最近一次会议的内容。
为什么会有两个 IDE?
rust-analyzer 的主要优点是性能更佳(因为它采用了完全惰性的编译模型)和功能集更丰富(因为它提供了更灵活的分析 API)。RLS 的主要优点是精确性(它底层使用了 rustc
)。此外,RLS 是 save-analysis 基础设施的主要使用者,这非常适合需要代码库静态视图的工具,例如 cargo-src 或 lsif。
Save-analysis
什么是 “save-analysis”?它是一种不稳定的格式,rustc
用它来记录有关编译代码的信息。它包含相当高层的信息。例如,对于源 crate 中的每个标识符,save-analyzer 会将此标识符映射到定义和用法列表。可以使用 env RUSTFLAGS="-Zunstable-options -Zsave-analysis" cargo check
命令指示 rustc
生成 save-analysis 文件(JSON 格式)。由于 save-analysis 是直接从 rustc
内部数据结构生成的,因此可以保证其正确性(除去 rustc
本身的错误)。
查询模型
save-analysis 的根本问题在于它是为整个 crate 一次性计算的。这对于非平凡的 crate 来说相当慢,而且也很浪费。在任何特定时刻,真正需要的分析信息只占一小部分。rust-analyzer 通过使用 salsa
查询来进行代码分析来解决这个问题。结果是构建了一个在整个 crate 图上完全惰性的编译模型。这个模型类似于 rustc
内部使用的模型,但在“垂直”和“水平”方向上都更惰性。垂直方面,rustc
只有在解析和宏展开后才开始增量;rust-analyzer 是基于文件的增量。水平方面,rustc
一次编译一个 crate;rust-analyzer 对整个 crate 图使用查询。
前进方向
我们目前的假设是,无需投入双倍的工程精力即可整合这两种方法。具体来说,我们将在 rust-analyzer 中添加一个选项,使其使用 save-analysis 来实现查找用法和重命名功能。这样,我们就可以在不降低补全速度的情况下,获得最重要查询的精确结果。然而,与 RLS 不同的是,rust-analyzer 不会链接到 rustc
,而是依赖 cargo
来运行编译器并生成 save-analysis 数据。如果这种方法可行,我们将考虑冻结 RLS 并完全专注于 rust-analyzer。从长远来看,计划是将 save-analysis 回退路径与惰性分析统一起来。
与 RLS/rust-analyzer 统一工作并行,我们继续推进 rustc
的库化(library-ification),特别关注 trait 求解(通过 chalk)和类型推断。“库化”是我们用来描述将代码从 rustc
中提取出来,形成可重用库,供 rustc
和 rust-analyzer 共享的过程。目标是利用库化逐渐减少 rustc
和 rust-analyzer 之间的重复代码,最终目标是要么拥有一个单一的代码库,要么绝大部分逻辑都共享。