特性工作组 2020 年冲刺 1 总结

2020 年 3 月 28 日 · Jack Huey 代表 特性工作组

本周二,特性工作组结束了 2020 年的第一次冲刺,从 2 月 11 日持续到 3 月 24 日,共 6 周。上一次冲刺大约在一年前,但我们决定恢复这种形式,以帮助推进 Chalk 和 rustc 中与特性相关的工作。

特性工作组是什么?我们在做什么?

目标:一个高效、可扩展、可重用的 Rust 特性系统 crate

特性工作组 的首要目标是创建 Rust 特性系统一个高性能、可扩展且清晰的实现。这个实现不仅应该能支持现有的 Rust 特性,还应该能支持新的以及即将到来的特性,例如

除此之外,我们还希望实现是可重用的——这意味着它不仅可以被 rustc 使用,还可以被 rust-analyzer 以及其他可能的场景使用。

这项工作是编译器团队一个重要的长期目标的一部分:库化。这是指将编译器分解成独立的库,可以独立学习、测试和开发。

为了实现这些和未来的特性,我们的工作分为两部分:1) 改进 rustc 现有的特性求解器。2) 设计和实现 Chalk 特性求解器,并努力将其集成到 rustc 中。简而言之,Chalk 特性求解器是一个基于逻辑的特性求解器,设计上独立于 rustc 内部。除了比当前 rustc 特性求解实现更强大之外,Chalk 还可以用作编译器相关工作的库,例如 IDE 集成(例如 rust-analyzer)。

进入 2020 年,我们——特性工作组——知道我们想要更有条理,并更加努力地将 Chalk 完全集成到 rustc 中,通过清理 Chalk 代码库本身、修复 bug、实现新特性,并最终将 Chalk 集成到 rustc 自身。此外,我们致力于记录设计考量和决策,以便现在和将来更容易理解。例如,我们现在发布了一本 Chalk ,虽然不完整,但尝试文档化 Chalk 的内部细节,类似于 rustc 开发指南

关于 Chalk 集成到 rustc 中的说明

Chalk 的实验性集成曾存在于 rustc 中(使用 -Z chalk 标记),持续了一年多,但自从最初实现以来,在这方面的进展甚微,而 Chalk 本身却做了大量工作。这最终意味着基于旧版 Chalk 的最初实现与基于当前 Chalk 的实现应该有的样子大相径庭。基于此理由,该实验性实现已被移除。

2020 年冲刺 1

好的,背景介绍完毕,接下来进入实际的 2020 年冲刺 1。开始之前,我们并不太确定我们的目标是什么。在这篇文章中,我们将分享这次冲刺中完成的各项工作概述,实际上成果相当多!

致谢

非常感谢 :hearts: 参与本次冲刺的各位

特性工作组技能树

我们的“技能树”是我们跟踪我们的开发路线图的方式。它展示了我们正在努力实现的一些主要目标(例如,使 chalk 可用作独立库)以及在此过程中必须完成的一些主要任务。您可以点击任务链接查看相关的 github issue 或其他解释。我们尽量在每次会议后更新它,以便了解我们正在做什么以及原因。

技能树的结构灵感来源于 这篇关于 WebAssembly 的博客文章,这篇文章又借鉴了游戏中的术语。可惜的是,目前生成技能树的工具还无法像 WASM 文章中的手绘图一样美观。如果有人有兴趣改进该工具的输出,这将是即将到来的冲刺的“延伸目标”之一!

Chalk 书籍的 chalk-engine 章节

如前所述,为了文档化 Chalk 的内部细节,我们去年年底开始出版一本。在本次冲刺接近开始时,我们添加了关于chalk-engine 自身的整个章节。这是 Chalk 的核心 crate,用于解决一组给定的 Goal。虽然总有更多可以文档化的内容,但我们希望这至少能帮助人们,特别是新手,理解 Chalk 的内部工作原理。

实现对 impl Trait 的基本支持

在 Rust 中,目前以及未来,你可以在一些地方指定 impl Trait 而不是具体的结构体。例如,函数的签名可以是 fn foo() -> impl Debug。未来,你可能还会使用 impl Trait 语法的地方是配合 type Foo = impl Trait(目前在 type_alias_impl_trait 特性下)。这将允许你像使用具体类型一样使用 Foo。在本次冲刺中,我们在让这两者都能与 Chalk 协同工作方面取得了显著进展。我们将在接下来的冲刺中进行后续工作,并有望落地支持。

提出共享类型库的方案

目前,rustc、rust-analyzer 和 chalk 各自使用不同的结构体集来表示 Rust 类型。这意味着当 rustc 或 rust-analyzer 希望调用 chalk 函数时,我们必须来回转换 Rust 类型的表示。这暂时还可以接受,但最终我们希望所有人使用相同的表示,这样就不需要相互转换了。然而,这有点棘手,因为 rustc(一个批处理编译器)和 rust-analyzer(一个 IDE)的需求有所不同。在本次冲刺中,我们起草了一份共享类型库的方案,并就此主题召开了一次设计会议。您可以在这里找到会议记录,其中也包含了该方案。

在接下来的冲刺中,我们将根据这项设计,开始在 rustc 中进行一些初步的重构工作。

重构以传递 Interner

共享类型库的要求之一是需要支持类型的 interning(实习)和 arena allocation(竞技场分配)。Interning 一个类型意味着每次遇到等价类型时重复使用相同的内存,而不是分配多个副本。Arena allocation 是一种内存管理策略,您将所有内存分配在一个不断增长的池中,然后一次性释放整个池,而不是跟踪和释放单独的分配。

然而,Chalk 现有的类型库在实现时考虑的是简洁性,无法支持这两种用例。问题在于,要支持 interning 和 arena allocation,需要跟踪一个包含哈希映射、arena 和其他支持数据结构的 interner 变量,而 chalk 的 API 没有为此预留空间。本次冲刺,我们修复了这个问题,现在我们在 chalk 中全程传递一个 interner 值,这意味着我们可以更轻松地与 rustc 和 rust-analyzer 进行桥接。

重构 chalk 表示绑定类型和生命周期的方式

Chalk 表示带有绑定变量的类型(例如,for<'a> fn(&'a u32) 中的 'a)的一些细节与 rustc 处理这类类型的方式有所不同。这使得从 rustc 到 chalk 的桥接困难得多。我们发现最终想要的设计是 rustc 和 chalk 现有方案的混合。在本次冲刺中,我们完成了大部分 chalk 的重构工作,在接下来的冲刺中,我们将着手 rustc 方面的工作。

实现对 Chalk 的 tracing 支持

tracing crate 提供了一个用于收集基于事件的诊断信息的框架。目前,Chalk 中只有基本的日志支持。通过添加 tracing 支持,我们期望获得对 Chalk 诊断更精细的控制。初步支持已接近完成,有望很快合并。

探索性 rustc 集成 MVP

如前所述,由于过时,之前实验性的 Chalk 集成已从 rustc 中移除。因为 Chalk 和 rustc 当前的特性求解器之间存在不少设计差异,有些还很微妙,所以不总是清楚究竟需要修改什么才能使其正常工作。我们已经开始编写实验性的 Chalk 集成。目标,至少在开始阶段,是创建一个最小实现作为未来工作的基础。虽然拉取请求还没有完全到位,但已经很接近了,并且在发现 Chalk 中阻碍进展的阻塞性问题方面非常有帮助。

探索性递归求解器

chalk 设计的一个有趣之处在于它将求解策略与特性系统实现的其他部分分离开来。除了我们现有的求解器,即所谓的“按需 SLG 求解器”,我们还在探索一种“递归求解器”设计。我们首先恢复了这段代码的一个旧版本,该版本曾被移除,并且一直在探索如何将其适应新的想法。

Chalk 小幅清理

在过去的冲刺中,Chalk 进行了一些小的清理工作值得一提。它现在又能构建 rustc 并通过 rustc 的 lints 了。我们移除了一些不必要的依赖(好吧,技术上说它是用于测试的)。最后,我们还让 Chalk 在 panic 方面更安全了一点。

2020 年冲刺 2

我们计划在下周二,即 3 月 31 日,开始 2020 年的下一次冲刺。我们将简要介绍几个目标

如何参与

如果您想参与其中,请加入 rust-lang Zulip#wg-traits 流。我们还有一个每周设计会议(在 Zulip 上举行),我们用它来同步进展并讨论棘手的问题。

Chalk rustc 集成 MVP

这可能会有些挑战,但我们希望在本次冲刺中完成 Chalk-rustc 集成的“最小可行产品”(MVP),以便推动进一步开发。这个 MVP 将是不完善且不完整的(例如,它可能无法正确执行借用检查器规则),但这将帮助我们发现边缘情况并验证 chalk 求解器的设计。为此,我们有许多具体的任务

  • 扩展 chalk,使其支持 SizedCopyClone 等内置特性
    • 有一些特性,其精确规则并非通过普通 impls 来表达,而是需要在库本身进行特殊集成。Chalk 目前不支持这些特性,所以我们需要对其进行扩展。
  • 合入现有分支
  • 将 rustc 类型转换为 chalk 类型
    • 最终,我们希望 rustc 和 chalk 共享同一个类型库,这样它们之间就不需要桥接了。但创建这样一个库需要一段时间。所以,在此期间,我们将编写代码,按需将 rustc 类型转换为 chalk 类型。(与此同时,其他一些冲刺目标将是调整 rustc 类型,以便我们也朝着最终目标前进。)

关于 const 集成的设计会议

如前所述,我们最初的 Chalk rustc 集成 MVP 将不支持 const。在本次冲刺中,我们计划安排一次设计会议,专门详细讨论 const 将会是什么样的设计。实际的实现工作将留到后续的冲刺中进行。

推动 rustc 和 Chalk 类型对齐

在本次冲刺中,我们计划开始着手提取一个用于 Rust 类型的共享库,如前述设计会议所讨论的。这将涉及对 rustc 进行重构以及对 chalk 进行修改。(跟踪 issue。

合入对 impl Trait 的基本支持

我们预计在下次冲刺早期就能合入对 impl Trait 的基本支持。然而,还需要进行一些后续工作来进一步完善实现。

探索性实现与研究

除了更具体的目标外,还有一些探索性工作正在进行中

Chalk 性能工作

Chalk 的大部分工作都集中在设计上,而优化性能方面做得不多。虽然这里的具体“最终目标”尚不明确,但我们希望首先为 Chalk 创建一套内存、CPU 和时间基准测试。有了这个框架,我们可以诊断特定的性能问题,并监控未来的更改是否引入性能回归。这部分工作包括合入 tracing 支持。

改进技能树

技能树是一个有用的工具,帮助我们组织工作并跟踪状态和整体计划。然而,当前的输出并不完全自明,也不特别吸引人。最终目标是生成类似于 Lin 手绘作品的图片。此外还缺少一些特性。如果有人有兴趣尝试改进输出质量或添加特性,那将是极好的!技能树位于它自己的 github 仓库中,但只需在 Zulip 的 #wg-traits 流中与我们交流即可。