Trait 工作组 2020 年第三次冲刺总结

2020 年 7 月 17 日 · Jack Huey 代表 Trait 工作组

又来了?感觉我们才刚做完一次……6 周前 😉。无论如何,这次冲刺的大部分内容是前两次的延续:努力使 Chalk 功能完整,并最终在 rustc 中使用它进行 trait 求解。

如果有人以前没看过此类总结,如果你对 trait 工作组感到好奇,可以在这里找到摘要。

功劳归属

一如既往,非常感谢所有参与本次冲刺的人员

Chalk crate 清理和每周发布

自成立以来,Chalk 在其 crate 的结构方面经历了很多更改,这对于任何规模合理的项目来说都是正常的。在本次冲刺中,我们花时间稍微清理了一下 crate 的结构。最好简单概述一下我们最终的结果。更全面的概述可以在Chalk 书籍中找到。

  • chalk-derive - 定义派生 proc 宏
  • chalk-ir - 一个基本的“类型库”,将来可能会在 rustc、Chalk 和 rust-analyzer 之间共享
  • chalk-solve - 定义 chalk-ir 中类型的 Rust 语义
  • chalk-engine - 实现 SLG 求解器
  • chalk-recursive - 实现递归求解器
  • chalk-parse - 用于测试,将类似 Rust 的语法解析为 chalk-irchalk-solve 类型
  • chalk-integration - 用于测试,提供用于测试的有用类型
  • chalk - 用于测试,提供 REPL

在此次冲刺期间,我们还设置了 Chalk crate 的定期每周发布。虽然目前这些都是 0.*.0 的补丁版本,但它为未来的稳定版本建立基础设施,并提供在 rustc 和 rust-analyzer 中使用的已发布的 crate。将来,当 Chalk 开发更加稳定时,我们希望将其切换为手动发布。我们还计划设置 bors 以确保 master 始终构建并通过测试。

努力在 rustc 中支持 GAT

Chalk 早就支持 GAT;在 Chalk 术语中,GAT 是其他一切的自然扩展。但是,rustc 中的 GAT 比较困难,并且在过去的几年中一直处于停滞状态,主要重点是使 Chalk 做好准备。但是,最近在 rustc 中进行了一些工作,以使 GAT 在当前的 rustc trait 系统下工作。

提取表示类型的共享库

作为一个长期目标,我们希望有一天能在 Chalk 和 rustc 之间共享一个类型库。此外,此类型库可以用于其他项目,例如 rust-analyzer。在 Chalk 方面,添加了更多类型(例如闭包和枚举)和更多 trait(例如 Fn 系列和 Unsize)。此外,还完成了一些工作以反方向发展:使 rustc 更接近 Chalk,例如 实习 Predicate,以及 引入 ForAll 谓词

编写 .chalk 文件进行调试

作为 Chalk 测试的一部分,我们可以编写类似 Rust 的“程序”,这些程序被解析为 Chalk 类型。重要的是,这些程序比它们降低到的类型简洁得多。作为更好地进行调试工作的一部分,我们实现了一个反方向的系统:能够从底层类型生成类似 Rust 的程序。这对于例如调试 rustc 尝试编译的给定代码的错误非常有用。此外,它还可以用于生成具有性能问题的案例的程序。

改进 impl Trait 支持

在上次冲刺中,我们实现了初始的 impl Trait 支持,以处理类似 type Foo<T> = impl Bar 的简单情况。在此次冲刺中,我们开始添加对更复杂情况的更多支持,例如 type Foo<T>: Debug = impl Bar where T: Debug。此外,还完成了一些设计工作来支持检查它们是否格式正确。

扩展 Chalk 以支持 Rust 语义

这个目标与“提取共享类型库”有点重叠,但它不是关于表示类型本身,而是更多关于表达这些类型的语义。例如,考虑以下程序

trait Foo: Sized {
    fn foo(self) {}
}
impl Foo for u32 {}
impl Foo for String {}

fn main() {
  let x = 0;
  x.foo();
}

在当前冲刺之前,Chalk 无法正确处理此问题;它不知道你可以在 0 上调用 foo。实际上,为了能够正确编译此程序,编译器必须知道 0 永远不可能是 String。考虑一下如果你将 String 的 impl 更改为 u64 会发生什么:rustc 不知道你希望 0u32 还是 u64。这基本上是 Chalk 在本次冲刺之前看到此程序的方式。但是,Chalk 现在可以正确处理这种情况。

处理 rustc 集成中的生命周期约束

因此,作为 trait 求解的一部分,Chalk 和 rustc 有时可能会发现一个生命周期需要比另一个生命周期更长,或者一个类型必须比一个生命周期更长。例如,

trait Foo<'a, 'b, T> where 'a: 'b, T: 'a  {}

Chalk 不会单独解决这些生命周期约束,而是将它们传递回 rustc。在此次冲刺中,我们添加了在 Chalk 中表达这些 where 子句的功能。

其他工作

在此次冲刺中完成了很多较小的工作,这些工作实际上不适合单独的目标。Chalk 在其建议中变得更聪明了。我们引入了用于日志记录的 tracing。我们为递归求解器做了一些设计工作。当然,还有大量的内部重构和清理。当然,rustc 集成也跟上了最新版本的 Chalk 功能并进行了更新。

暑假

今年到目前为止很忙!自 2 月初开始第一次冲刺以来,我们取得了巨大的进步。但是,与过去的几次冲刺不同,我们不会立即开始下一次冲刺。相反,我们将休息几个月,并在 9 月重新开始。在那之前,我们不会在 Zulip 上举行每周会议,也不会有任何确定的目标。这部分是因为一些成员可能会休假。而且,代码倦怠非常真实,偶尔休息一下会有所帮助。与此同时,还剩下一些需要完成/清理的项目。

如果你有兴趣帮忙,请不要气馁!Zulip 应该仍然相当活跃,所以请随时光临!