Rustc Trait System Refactor Initiative 更新:征集测试

2023 年 12 月 22 日 · lcnr 代表 Rustc Trait System Refactor Initiative

上次更新以来,已经快半年了。我们正在重新实现 rustc 的 trait solver,目标是完全替换现有系统。这应该能帮助我们修复一些长期存在的错误,支持未来的类型系统改进,并减少编译时间。详细介绍请参阅上次更新。我们在新的 solver 上取得了很大进展,主要集中在使其能在 coherence 中使用。我们修改了不稳定编译器标志来启用新的 solver:您现在可以使用 -Znext-solver=globally 在任何地方启用它,使用 -Znext-solver=coherence 仅在 coherence 检查时启用新的 solver。

trait solver 的重新实现现已准备好在 coherence 检查中使用,coherence 检查负责防止 trait 实现重叠。已知的所有与旧 solver 的行为变化都是有意为之的,并且错误消息的质量应与现有实现相匹配。然而,在过去几个月中,非致命溢出的处理已成为最重要和最复杂的问题之一。

非致命溢出

与现有 trait solver 不同,新的 solver 在达到递归限制时不会立即中止编译

struct Wrapper<T>(T);

trait Overflow {}
impl<T> Overflow for Wrapper<Wrapper<T>> where Wrapper<T>: Overflow {}
impl Overflow for Wrapper<u32> {}

// Checking whether these two implementations overlap
// tries to prove that either `Wrapper<_>: Overflow` or
// `Wrapper<_>: Copy` do not hold.
//
// The existing solver first checks `Wrapper<_>: Overflow`,
// resulting in overflow and aborting compilation.
//
// The new solver does not abort compilation on overflow and
// considers the implementations to be disjoint, given that
// `Wrapper<_>: Copy` does not hold.
trait MayOverlap {}
impl<T: Overflow + Copy> MayOverlap for T {}
impl<T> MayOverlap for Wrapper<T> {}

这种改变是必要的,因为流行的 crate,例如 typenum,在使用新的 solver 时现在会达到递归限制,如果溢出仍然是致命的,就会导致它们无法编译。这是由移除旧 solver 中存在的启发式算法引起的。它也是期望的,因为编译结果在其他情况下是顺序依赖的。这种顺序依赖性使得未来对类型系统的更改复杂化,例如在旧 solver 中尝试切换到延迟投射等式也最终在 typenum 中导致了溢出错误,阻止了其合并。用户也可以观察到这一点,例如在上面的例子中将 where-clauses 的顺序切换到 T: Copy + Overflow 会导致这段代码在使用旧 solver 时可以编译。

新的 solver 在达到递归限制时现在会返回溢出。然而,这种改变本身会导致 solver 由于指数级膨胀而非常容易挂起。因此,我们在遇到溢出后,会极大地限制后续目标的可用递归深度,并丢弃由溢出引起的目标的一些推理约束。

平衡 trait solver 的性能与 trait 系统表现力非常重要。虽然我们对目前确定的方法相当满意,但要做好这一点更多是艺术而非科学。我们相信我们目前的方法在大多数情况下是高性能的,并允许未来进一步进行显著的性能优化。我们也期望它能提供必要的表现力,以与旧 solver 向后兼容,并符合用户的预期行为。

展望未来并征集测试

由于我们相信在 coherence 检查中使用新的 solver 现已达到稳定化准备状态,请通过启用不稳定编译器标志 -Znext-solver=coherence 来试用新的实现。如果您遇到任何行为或性能退步、诊断问题,甚至是健全性问题(unsoundnesses)1,请在 GitHub 上提交问题

在 coherence 检查期间使用新的 solver 将改进一些边缘情况下的行为,至少修复一个几乎不可被利用的健全性问题(unsoundness)。它还将允许我们移除现有 solver 中对“跨 crate 模式(intercrate mode)”的支持。然而,使用新 solver 的大部分积极影响2只有在更多领域使用它时才会显现。

因此,我们打算稍微延迟其在 coherence 中使用的稳定化,以确保我们的设计选择不会在未来引起复杂问题。展望未来,我们将重新把工作重点放在全面启用新的 solver 上。通过修复 -Znext-solver=globally 模式下更多的剩余问题,我们应该能对我们的溢出处理方法更有信心。我们预计在 2024 年 3 月实际稳定新的 solver 在 coherence 中的使用,并打算在此之前提供额外的学习资料和文档。

如果对新的 solver 有任何问题或想法,请在 zulip 上联系我们。