Google Summer of Code 2025 成果 | Rust 博客
2025年11月18日 · Jakub Beránek, Jack Huey
代表指导团队
正如我们今年早些时候宣布的那样,Rust项目第二次参与了谷歌编程之夏(GSoC)。近二十名贡献者在几个月内非常努力地完成了他们的项目。与去年一样,项目的持续时间各不相同,因此一些项目在9月结束,而最后一个项目在11月中旬完成。现在所有项目的最终报告都已提交,我们很高兴地宣布,19个项目中有18个取得了成功!我们今年的项目数量非常多,因此我们认为这个成功完成的项目数量是一个很好的结果。
我们在夏天与GSoC贡献者进行了很棒的互动,通过视频通话,我们也有机会见面并讨论了接受的GSoC项目。我们的贡献者学到了很多新东西,并与我们合作,使Rust对每个人都更好,我们非常感谢他们所有的贡献!他们中的一些人甚至在项目结束后继续贡献,我们希望将来继续与他们合作,进一步改进开源的Rust软件。我们要感谢所有2025年Rust GSoC贡献者。你们做得非常出色!
与去年一样,2025年谷歌编程之夏对Rust项目来说总体上是成功的,这次项目数量增加了一倍多。我们认为GSoC是向我们的社区引入新贡献者的好方法,我们期待在不久的将来再次参与GSoC(或类似项目)。如果您有兴趣成为(GSoC)贡献者,请查看我们的GSoC项目创意列表和新贡献者指南。
下面您可以找到我们2025年GSoC项目的简要总结。您可以在此处找到有关项目原始目标的更多信息。为便于导航,以下是按字母顺序排列的项目描述索引:
- Marcelo Domínguez的自动微分功能的ABI/布局处理
- Dawid Lachowicz添加安全合约
- Michał Kostrubiec使用rustc_codegen_gcc引导rustc
- Naman Garg的Cargo:构建脚本委托
- Jiping Zhou的分布式和资源高效验证
- Talyn Veugelers在cargo-semver-checks中启用见证生成
- Madhav Madhusoodanan扩展std::arch intrinsics的行为测试
- Sakibul Islam在bors中实现合并功能
- Shourya Sharma改进bootstrap
- Kei Akiyama改进Wild链接器测试套件
- Lorrens Pantelis改进Rustc并行前端:并行宏展开
- Joseph Chung使cargo-semver-checks更快
- Francisco Gouveia使Rustup并发
- Julien Robert使用已建立的持续集成实践映射Rust的UI测试套件迷宫
- Abdul Muiz现代化libc crate
- Makai准备stable_mir crate发布
- Glen Thalakottur使用cargo check原型化cargo fix的替代架构
- Vito Secona原型化Cargo管道命令
现在请系好安全带,因为这里有很多精彩内容要阅读!
ABI/布局处理用于自动微分功能
贡献者: Marcelo Domínguez
导师: Manuel Drehwald, Oli Scherer
最终报告
std::autodiff模块允许计算微积分意义上的梯度和导数。它提供了两个autodiff宏,可以应用于用户编写的函数,并自动生成这些函数的修改版本,这些版本还计算请求的梯度和导数。这个功能在科学计算和机器学习模型实现的背景下特别有用。
我们的autodiff前端面临两个挑战。
首先,我们会通过宏展开生成一个新函数,但我们还没有合适的函数体。我们的autodiff实现依赖于LLVM插件来生成函数体。然而,这个插件只在编译管道的末尾被调用。早期的优化传递,无论是在LLVM还是Rust端,可能会查看占位符体并“优化”甚至删除函数,因为它还没有明确的目的。
其次,我们宏的灵活性导致了问题,因为它允许基于每个参数请求导数计算。然而,当我们将Rust参数降级到像LLVM这样的编译器后端时,我们并不总是有Rust参数到LLVM参数的1:1匹配。一个简单的例子,一个有两个双精度值的数组可能在LLVM级别作为两个单独的双精度值传递,而一个有三个双精度值的数组可能通过指针传递。
Marcelo帮助重写了我们的autodiff宏,不再生成临时的占位符函数体,而是引入了适当的autodiff内在函数。这是我们声明此函数的实现尚不可用并将在编译管道后期提供的正确方式。因此,我们生成的函数不再被删除或不正确优化。内在函数PR还允许删除一些先前的临时解决方案,因此减少了Rust编译器中的总代码行数超过500行!您可以在此PR中找到更多细节。
除了autodiff工作,Marcelo还启动了GPU卸载内在函数的工作,并帮助我们处理了参数处理中的多个错误。我们要感谢Marcelo的所有出色工作!
添加安全合约
贡献者: Dawid Lachowicz
导师: Michael Tautschnig
最终报告
Rust项目有一个雄心勃勃的目标,即用安全合约装备Rust标准库,从指定不安全函数安全要求的非正式注释转变为可执行的Rust代码。这种转变代表了使Rust的安全保证更加明确和可验证的重要一步。为了优先考虑哪些函数应首先接收合约,正在进行一个验证竞赛。
鉴于Rust合约仍处于早期阶段,Dawid的项目在范围和方向上是故意开放式的。这种灵活性使Dawid能够识别并解决几个将为合约生态系统增加重要价值的关键领域。他的贡献在以下三个主要领域:
- 实用合约集成: 重构合约HIR降级,确保当合约检查禁用时没有合约代码被执行。这有重大影响,因为它确保当合约检查禁用时合约没有运行时成本。
- 变量引用能力: 添加从后置条件中引用前置条件中变量的能力。这个对合约系统的基本增强已完全实现并合并到编译器中。这个功能为开发人员在编写合约时提供了更多表达能力,允许他们在输入和输出状态之间建立关系。
- 分离逻辑集成: Dawid项目的大部分涉及识别、理解和规划为不安全Rust代码的合约引入分离逻辑风格推理的拥有和块所有权谓词。这项工作需要广泛的研究和与该领域专家的合作。Dawid与Rust验证工具的作者和Miri开发人员进行了多次讨论,包括面对面和通过Zulip讨论线程。这项研究的高潮体现在Dawid创建的全面MCP(重大变更提案)中。
Dawid的工作代表了Rust安全合约计划的关键基础进展。通过成功实现变量引用能力并为分离逻辑集成奠定基础,他已经为这个重要安全功能的未来重大发展定位。他的研究和设计工作无疑将影响这个重要安全功能随着成熟的方向。非常感谢!
使用rustc_codegen_gcc引导rustc
贡献者: Michał Kostrubiec
导师: antoyo
最终报告
这个项目的目标是改进Rust GCC代码生成后端(rustc_codegen_gcc),使其能够再次编译“阶段2”¹ Rust编译器(rustc)本身。
您可能记得Michał去年已经参加了GSoC,他在那里从事自己的.NET Rust代码生成后端工作,他做了大量工作。今年,他的进展甚至更快。在官方GSoC实施期开始之前(!),他基本上完成了他的原始项目目标,并设法用GCC构建rustc。这不是一个小壮举,因为他必须调查并修复几个错误编译,这些错误发生在标记为#[inline(always)]的函数被递归调用时,或者当编译的程序试图处理128位整数时。您可以在他的博客上阅读有关这项初始工作的更多信息。
之后,他立即开始处理项目的延伸目标。第一个是让“阶段3”rustc构建工作,为此他必须大幅改进代码生成后端的内存消耗。
一旦完成,他继续处理另一个目标,即为LLVM不支持的平台构建rustc。他在Dec Alpha和m68k上取得了进展。他还尝试在Aarch64上编译rustc,这导致他发现了一个ABI错误。最终,他设法为m68k构建了一个rustc(带有一些我们将来需要修复的变通方法)。这是将Rust移植到LLVM不支持的新平台的一个非常好的第一步,并且对于Rust for Linux等计划很重要。
Michał必须花很多时间研究汇编代码并调查神秘的ABI问题。为了使这对每个人都更容易,他实现了在GCC代码生成后端中进行模糊测试和自动检查ABI不匹配的支持。您可以在此处阅读有关他的测试和模糊测试工作的更多信息。
我们对Michał能够实现的目标印象深刻,我们非常感谢今年夏天与他合作。感谢您的所有工作,Michał!
Cargo:构建脚本委托
贡献者: Naman Garg
导师: Ed Page
最终报告
Cargo构建脚本带来编译时成本,因为即使运行cargo check,它们也必须像运行cargo build一样构建,以便它们可以在编译期间执行。尽管我们试图找到减少首先需要编写构建脚本的方法,但这可能并不总是可行的。但是,如果我们可以将构建脚本从每个需要它们的包中定义转移到几个核心构建脚本包中,我们可以减少编译时开销,并提高它们的可审计性和透明度。您可以在此处找到有关此想法的更多信息。
将构建脚本委托给包所需的第一步是能够每个crate运行多个构建脚本,因此这是Naman主要工作的内容。他向Cargo引入了一个新的不稳定multiple-build-scripts功能,实现了在Cargo.toml中解析构建脚本数组的支持,并扩展了Cargo,使其现在可以在构建单个crate时执行多个构建脚本。他还添加了一组测试,以确保此功能按我们预期的方式工作。
然后他致力于确保构建脚本的执行以确定性顺序执行,并且crate可以分别访问每个构建脚本的输出。例如,如果您有以下配置:
|
|
那么相应的crate能够使用env!(“windows-manifest_OUT_DIR”)和env!(“release-info_OUTDIR”)访问两个构建脚本的OUT_DIR。
作为未来的工作,我们希望通过Cargo.toml中指定的元数据实现向构建脚本传递参数的能力,然后使用工件依赖实现对外部构建脚本的实际构建脚本委托。
我们要感谢Naman帮助改进Cargo并为可能在整个Rust生态系统中带来编译时好处的功能奠定基础!
分布式和资源高效验证
贡献者: Jiping Zhou
导师: Michael Tautschnig
最终报告
这个项目的目标是通过开发一个分布式验证系统来解决正式验证Rust标准库的关键可扩展性挑战,该系统智能管理计算资源并最小化冗余工作。Rust标准库验证项目在验证大型代码库时面临显著的计算开销,因为传统方法重新验证未更改的代码组件。随着Rust的标准库包含数千个函数和持续开发周期,这种低效率成为实际正式验证采用的主要瓶颈。
Jiping实现了一个具有几个关键创新的分布式验证系统:
- 智能变更检测: 系统使用基于哈希的分析来识别代码库的哪些部分实际发生了变化,允许验证仅关注修改的组件及其依赖项。
- 多工具编排: 项目协调多个验证后端,包括Kani模型检查器,具有仔细的版本固定和兼容性管理。
- 分布式架构: 验证工作负载分布在多个计算节点上,具有考虑计算要求和依赖图的智能调度。
- 实时可视化: Jiping构建了一个全面的Web界面,提供实时验证状态、交互式图表和详细的证明结果。您可以在此处查看!
您可以在此存储库中找到创建的分布式验证工具。Jiping的工作为可扩展的正式验证奠定了基础,可以适应Rust生态系统日益增长的复杂性,同时保持验证质量和完整性,这将大大有助于确保Rust的标准库保持安全和健全。感谢您的出色工作!
在cargo-semver-checks中启用见证生成
贡献者: Talyn Veugelers
导师: Predrag Gruevski
最终报告
cargo-semver-checks是一个Cargo子命令,用于查找Rust crate中的SemVer API破坏。Talyn的项目旨在为它解决我们最令人烦恼的限制奠定基础:无法捕获由于类型更改导致的SemVer破坏。
想象一个crate对其公共API进行了以下更改:
|
|
这显然是一个重大破坏性更改,对吧?然而,带有数百个lint的cargo-semver-checks仍然无法标记这一点。虽然这种情况看起来微不足道,但它只是一个巨大冰山的一角。如果不是将i64更改为String,而是从i64更改为impl Into
|
|
弄清楚这个更改是否破坏性需要检查原始i64参数类型是否可以“适应”那个impl Trait类型的怪物。但是在cargo-semver-checks内部重新实现Rust类型检查器和特征求解器是不可能的!相反,我们转向为先前对crates.io上的SemVer破坏研究创建的一种技术——我们生成一个“见证”程序,当且仅当两个版本之间存在破坏性更改时,该程序将无法编译。
见证程序是一个单独的crate,可以使其依赖于被扫描crate的旧版本或新版本。如果我们的示例函数来自一个名为upstream的crate,其见证程序将如下所示:
|
|
这个例子是精心挑选的,易于理解。见证程序很少这么简单!
尝试在插入新版本upstream的同时cargo check见证程序,强制Rust编译器决定i64是否匹配新的impl Trait参数。如果cargo check通过而没有错误,则这里没有破坏性更改。但是如果有编译错误,那么这是具体的、无可争议的破坏证据!
在过去的22周多的时间里,Talyn不知疲倦地工作,将这一点从一个想法变成了一个工作的概念证明。对于我们预见需要解决的每一个问题,沿途又出现了十个问题。Talyn做了很多设计工作,以找出一种能够处理来自各种来源(crates.io、磁盘上的路径、git修订版)的crate的方法,支持所有数百个现有lint的多种rustdoc JSON格式,并以不妨碍将来添加数百个更多lint的方式这样做。
即使上述令人生畏的挑战列表也无法公正地反映这个项目的复杂性。Talyn创建了一个见证生成原型,为将来稳健检查类型相关的SemVer破坏奠定了基础。这项工作的成功对于cargo-semver-checks 2026年及以后的路线图至关重要。我们要感谢Talyn的工作,我们希望将来继续与他们合作改进见证生成。
扩展std::arch intrinsics的行为测试
贡献者: Madhav Madhusoodanan
导师: Amanieu d’Antras
最终报告
std::arch模块包含目标特定的内在函数(通常对应单个机器指令的低级函数),旨在供其他库使用。这些旨在匹配C中作为供应商特定扩展可用的等效内在函数。
内在函数通过三种方法测试。我们测试:
- 内在函数的签名与架构指定的签名匹配。
- 内在函数生成正确的指令。
- 内在函数具有正确的运行时行为。
这些行为测试在intrinsics-test crate中实现。最初,这个测试框架仅覆盖AArch64和AArch32目标,在那里它在发现内在函数实现中的错误方面非常有用。Madhav的项目是关于重构和改进这个框架,使其更容易(或者真的,可能)扩展到其他CPU架构。
首先,Madhav将代码库拆分为一个具有共享(架构独立)代码的模块和一个具有ARM特定逻辑的模块。然后他实现了对x86架构内在函数测试的支持,这是Rust最广泛使用的目标。在这样做时,他允许我们发现一些内在函数实现中的真实错误,这是一个很好的结果!Madhav还在优化测试套件的编译和执行方式方面做了很多工作,以减少运行测试所需的CI时间,他为支持更多架构,特别是LoongArch和WebAssembly奠定了基础。
我们要感谢Madhav在帮助我们确保Rust内在函数安全正确方面的所有工作!
在bors中实现合并功能
贡献者: Sakibul Islam
导师: Jakub Beránek
最终报告
主要的Rust存储库使用一个我们称为bors的拉取请求合并队列机器人。它当前的Python实现有很多问题并且难以维护。因此,这个GSoC项目的目标是在我们的Rust重写中实现主要的合并队列功能。
Sakibul首先检查了原始Python代码库以弄清楚它在做什么,然后他实现了几个机器人命令,允许贡献者批准PR、设置它们的优先级、委托批准权、临时关闭合并树等等。他还实现了一个异步后台进程,检查给定的拉取请求是否可合并(这个过程相对复杂,由于GitHub的工作方式),这需要实现一个专门的同步队列,用于重复数据删除可合并性检查请求,以避免超载GitHub API。此外,Sakibul还重新实现了(一个更好版本的)合并队列状态网页,可用于跟踪哪些拉取请求当前在CI上测试,哪些已批准等。
在基础工作准备好后,Sakibul可以处理合并队列本身,这需要他考虑许多棘手的竞态条件和边缘情况,以确保bors不会例如将错误的PR合并到默认分支或多次合并PR。他用许多集成测试覆盖了这些边缘情况,以给我们更多信心,合并队列将按我们预期的方式工作,还准备了一个脚本,用于在测试GitHub存储库上创建模拟PR,以便我们可以“在野外”测试bors。到目前为止,它似乎工作得非常好!
在我们与Sakibul一起完成合并逻辑的最后一部分(创建所谓的“rollups”)后,我们将开始在主要Rust存储库中完全使用bors。因此,Sakibul的工作将用于合并所有rust-lang/rust拉取请求。令人兴奋!
除了处理合并队列,Sakibul还对代码库做出了许多其他很棒的贡献,比如重构测试套件或分析SQL查询性能。总共,Sakibul发送了大约五十个已经合并到bors中的拉取请求!我们还能说什么,除了:出色的工作Sakibul,谢谢!
改进bootstrap
贡献者: Shourya Sharma
导师: Jakub Beránek, Jieyou Xu, Onur Özkan
最终报告
bootstrap是Rust本身的构建系统,负责构建编译器、标准库以及几乎所有您可以通过rustup下载的其他内容。这个项目的目标非常开放:“改进bootstrap”。
而Shourya正是这样做的!他对bootstrap的几个部分做出了有意义的贡献。首先,他为几个核心bootstrap数据结构和模块添加了急需的文档,这些文档没有任何文档时相当不透明且难以理解。然后他转向改进命令执行,因为每个bootstrap调用调用数百个外部二进制文件,并且很难跟踪它们。Shourya完成了一个长期存在的重构,几乎将所有执行的命令通过单个地方路由。这使他能够实现命令缓存和命令分析,这向我们显示哪些命令最慢。
之后,Shourya转向重构配置解析。这不是一个简单的任务,因为bootstrap有很多配置选项;解析它们的单个函数有超过一千行代码(!)。一组复杂的配置优先级规则在我们必须修改该函数时经常导致错误。他花了几个星期来理清这个混乱,但结果是值得的。重构后的函数不那么脆弱,更容易理解和修改,这对将来的维护非常有益。
Shourya改进的最后一个领域是bootstrap测试。他使使用裸cargo运行它们成为可能,这使得例如在IDE中调试它们非常有用,主要是他找到了一种并行运行测试的方法,这使得对bootstrap本身的贡献更加愉快,因为它将执行测试的时间从一分钟减少到不到十秒。这些更改需要重构许多使用全局状态的bootstrap测试,这与并行执行不兼容。
总的来说,Shourya自4月以来向bootstrap提交了30多个PR!我们非常感谢他所有的贡献,因为它们使bootstrap更容易维护。谢谢!
改进Wild链接器测试套件
贡献者: Kei Akiyama
导师: David Lattimore
最终报告
Wild是一个用Rust编写的非常快的Linux链接器。它可以用于构建可执行文件和共享对象。
Kei的项目是利用其他Linux链接器之一的测试套件来帮助测试Wild链接器。这个目标已经完成。由于Kei的努力,我们现在在CI中针对Wild运行Mold测试套件。这有助于在至少几个场合防止回归,并也有助于显示Wild有改进空间的地方。
除了这项核心工作,Kei在GSoC期间还对Wild进行了许多其他更改。特别值得注意的是重新处理参数解析以支持–help,这是我们一段时间以来想要的。Kei还修复了一些错误并实现了各种以前缺失的功能。这项工作有助于扩展可以使用Wild构建可执行文件的项目范围。
Kei甚至在GSoC项目结束后继续为Wild做出贡献,现在已经贡献了七十多个PR。我们感谢Kei的所有辛勤工作,并期待未来的持续合作!
改进Rustc并行前端:并行宏展开
贡献者: Lorrens Pantelis
导师: Sparrow Li, Vadim Petrochenkov
最终报告
Rust编译器有一个(目前不稳定的)并行编译模式,其中一些编译器传递并行运行。
编译器的一个主要部分尚未受到并行化影响的是名称解析。 它有多个组件,但为此GSoC项目选择的是导入解析和宏展开(它们实际上混合到一个单一的不动点算法中)。
除了并行化本身,工作的另一个重要点是提高导入解析的正确性,通过消除其中的意外顺序依赖,因为这些也阻止并行化。
我们应该注意,这是一个非常雄心勃勃的项目,我们从一开始就知道,在短短几个月的时间内达到最终目标可能相当具有挑战性。事实上,Lorrens确实遇到了几个意外问题,这些问题向我们展示了这项工作的复杂性远远超出单个GSoC项目,因此他实际上没有开始并行化宏展开算法。尽管如此,他做了很多重要的工作来改进名称解析器并为其并行化做准备。
Lorrens必须做的第一件事实际上是理解Rust名称解析如何工作以及它如何在编译器中实现。说得委婉些,这是一个非常复杂的逻辑,并受到遗留负担的影响,形式为向后兼容lint、过时的命名约定和其他技术债务。即使这些学到的知识本身也非常有用,因为今天理解Rust名称解析的人集非常少,所以增长它很重要。
利用这些知识,他进行了许多重构,将名称解析器数据结构中的显著可变性与用于诸如从外部crate延迟加载否则不可变数据的“类似缓存”可变性分开,这是解锁并行化工作所需的。他拆分了解析器的各个部分,摆脱了不必要的可变性,并执行了一堆其他重构。他还必须想出一个非常棘手的数据结构,允许有条件地提供对某些数据的可变访问。
这些重构使他能够实现称为“批处理导入解析”的东西,它将crate中未解析的导入拆分为“批次”,其中单个批次中的所有导入可以独立且可能并行解析,这对于并行化名称解析至关重要。我们必须解决一些剩余的语言兼容性问题,之后批处理导入解析工作有望合并。
Lorrens为解决名称解析和宏展开周围潜在正确性问题奠定了重要基础,这解锁了进一步并行化这些编译器传递的工作,这令人兴奋。他的工作还有助于解锁一些长期停滞的库改进。我们感谢您在改进Rust及其编译器的棘手部分方面的辛勤工作,Lorrens。谢谢!
使cargo-semver-checks更快
贡献者: Joseph Chung
导师: Predrag Gruevski
最终报告
cargo-semver-checks是一个Cargo子命令,用于查找Rust crate中的SemVer API破坏。它正在以指数速度添加SemVer lint:lint数量每年翻倍,目前为229个。更多lint意味着cargo-semver-checks要做更多工作,以及其运行超过250000个lint检查的测试套件要做更多工作!
Joseph的贡献采取三种形式:
- 改进cargo-semver-checks运行时性能——在大型crate上,我们的查询运行时从
8s减少到2s,提高了4倍! - 改进测试套件的性能,使我们能够更快地迭代。我们的测试套件过去需要
7分钟,现在在1分钟内完成,提高了7倍! - 改进我们分析查询性能和检查性能异常的能力,这两者都被证明是我们能够交付进一步改进的瓶颈。
Joseph在他的最终报告中描述了导致这些结果的所有巧妙优化技巧。为了鼓励您查看帖子,我们将重点介绍那里描述的一个特别优雅的优化。
cargo-semver-checks依赖于rustdoc JSON,这是Rust的一个不稳定组件,其输出格式经常有破坏性更改。由于每个cargo-semver-checks版本支持一系列Rust版本,它还必须支持一系列rustdoc JSON格式。幸运的是,每个文件带有一个版本号,告诉我们使用哪个版本的serde类型来反序列化数据。
以前,我们曾经两次反序列化JSON文件:一次使用仅加载format_version: u32字段的serde类型,第二次使用匹配格式的适当serde类型。这工作正常,但许多大型crate生成500 MiB+大小的rustdoc JSON文件,要求我们两次遍历所有这些数据。虽然serde相当快,但没有什么比首先不做两次工作更快!
所以我们使用了一个技巧:乐观检查format_version字段是否是JSON文件中的最后一个字段,这每次都是这种情况(即使不能保证)。不是解析JSON,我们仅仅在最后几十个字节中查找,字符,然后在,字符后查找:字符,并在它们之间查找format_version。如果成功,我们在避免遍历数百MB数据的同时发现了版本号!如果由于任何原因失败,我们只是回退到原始方法,只浪费了查看大约20个额外字节的努力。
Joseph做了很多分析和性能优化,使cargo-semver-checks对每个人都更快,取得了惊人的结果。非常感谢您的工作!
使Rustup并发
贡献者: Francisco Gouveia
导师: rami3l
最终报告
作为Rustup团队将rustup代码库迁移到使用异步IO的愿景的一个非常重要部分,自从在#3367中引入全局tokio运行时以来,这个项目的目标是向rustup引入适当的并发性。Francisco通过同时攻击代码库的两个方面来做到这一点:
- 他创建了一组新的用户界面用于显示并发进度。
- 他实现了一个新的工具链更新检查和安装流程,这是习惯性并发的。
作为热身,Francisco使rustup check并发,导致在某些情况下相当容易的3倍性能提升。沿途,他还引入了一个新的基于indicatif的进度条,用于报告并发操作的进度,取代了原始的手动解决方案。
之后,项目的重点转移到用于命令如rustup toolchain install和rustup update的工具链安装流程。在这一部分,Francisco开发了两个主要改进:
- 在设置工具链时同时下载多个组件的可能性,由RUSTUP_CONCURRENT_DOWNLOADS环境变量控制。将此变量设置为大于1的值在某些互联网环境中特别有用,其中单个下载连接的速度可能受到QoS(服务质量)限制的限制。
- 交错组件网络下载和磁盘解压的能力。目前,解压仍将顺序发生,但磁盘和网络I/O终于可以重叠!这引入了工具链安装时间的净增益,因为只有最后下载的组件会有明显的解压延迟。在我们的测试中,当使用默认配置文件设置工具链时,这通常减少4-6秒(在快速连接上,这快了约33%!)。
我们必须说这些结果非常令人印象深刻!虽然短几秒钟的工具链安装可能乍看起来不那么重要,但rustup在数万个Rust项目的CI上普遍用于安装Rust工具链,因此这个改进(以及它解锁的进一步改进)将在整个Rust生态系统中产生巨大影响。非常感谢Francisco Gouveia的热情和积极参与,没有这些,这将无法实现!
使用已建立的持续集成实践映射Rust的UI测试套件迷宫
贡献者: Julien Robert
导师: Jieyou Xu
最终报告
基于快照的UI测试套件是Rust编译器测试套件的重要组成部分。它包含很多测试:在撰写本文时超过19000个。因此,这个测试套件的组织非常重要,至少有两个原因:
- 我们希望能够找到特定测试,识别相关测试,并对相关测试进行某种逻辑分组。
- 我们必须确保没有目录包含太多条目,以至于GitHub放弃渲染目录。
此外,拥有信息丰富的测试名称并为每个测试提供一些上下文特别重要,否则贡献者将不得不从git blame和朋友反向工程测试意图。
Julien的项目是关于在混乱中引入一些秩序。而这确实实现了!
通过Julien的努力(结合其他贡献者的努力),我们现在有:
- 在直接tests/ui/顶级目录下不再有流浪测试,并组织到更有意义的子目录中。我们然后能够引入样式检查以防止添加新的流浪测试。
- 一个顶级文档包含每个直接子目录的TL;DR。
测试组织(以及更一般地说,测试套件人体工程学)是维护复杂代码库的一个经常被低估的方面。Julien花了大量精力改进Rust编译器的测试人体工程学,既在去年的GSoC中(他大大改进了我们的“run-make”测试套件),然后今年再次,他使我们的UI测试套件更符合人体工程学。
我们感谢您细致的工作,Julien!非常感谢。
现代化libc Crate
贡献者: Abdul Muiz
导师: Trevor Gross
最终报告
libc是Rust生态系统中的一个关键crate(平均每天有约150万次下载),提供对系统C API的绑定。这个GSoC项目有两个目标:改进我们当前拥有的测试,并为libc的稳定1.0发布取得进展。
测试生成由ctest crate处理,它创建单元测试,将Rust API的属性与它绑定的C接口的属性进行比较。在项目之前,ctest使用一个已停止接收重大更新约八年的过时Rust解析器,意味着libc不能轻易使用比那更新的任何语法。Abdul完全重写了ctest以使用syn作为其解析器,并使其更容易添加新测试,然后通过并切换所有内容到更现代的ctest。在此更改后,我们能够删除许多与旧解析器一起工作所需的临时解决方案。
项目的另一部分是为libc的1.0发布取得进展。Abdul通过处理并解决许多需要在发布前解决的问题来帮助这一点,其中许多问题在所有ctest更改后成为可能。
虽然在libc达到1.0之前还有很多工作要做,但Abdul的改进将大大有助于使这项工作更容易,因为它们使我们对测试套件更有信心,测试套件现在更容易修改和扩展。非常感谢您的所有工作!
准备stable_mir crate发布
贡献者: Makai
导师: Celina Val
最终报告
这个项目的目标是准备Rust编译器的stable_mir crate(最终重命名为rustc_public),它提供了一种与Rust编译器接口以分析Rust代码的方式,以便在crates.io上发布。虽然现有的crate为工具开发人员提供了更简单的API,但它缺乏适当的版本控制,并且与编译器版本紧密耦合。目标是启用具有语义版本控制的独立发布。
主要技术工作涉及通过反转它们的依赖关系来重构rustc_public和rustc_public_bridge(以前命名为rustc_smir)。Makai通过临时合并crate并逐渐用新架构分离它们来解决循环依赖。他们还拆分了现有的编译器接口,将公共API与内部编译器细节分开。
此外,Makai建立了双重维护的基础设施:在Rust存储库中保留一个内部版本以跟踪编译器更改,同时在专用存储库中开发可发布版本。Makai自动化了一个系统来协调版本之间,并开发了自定义工具来验证编译器版本兼容性并运行测试。
Makai成功完成了核心重构和基础设施设置,使得可以独立发布具有适当版本支持的rustc_public,为Rust工具生态系统服务!作为奖励,Makai贡献了几个错误修复并实现了社区请求的新API。干得好Makai!
使用cargo check原型化cargo fix的替代架构
贡献者: Glen Thalakottur
导师: Ed Page
最终报告
cargo fix命令应用lint建议的修复,这使得它对于清理草率代码、减少当lint更改时工具链升级的烦恼以及帮助版本迁移和新lint采用很有用。然而,它有许多问题。它可能很慢,它只应用可能lint的一个子集,并且不提供简单的方法来选择要修复哪些lint。
这些问题是由其当前架构引起的;它被实现为cargo check的一个变体,用cargo在特殊模式下运行替换rustc,该模式将循环调用rustc,应用修复直到没有。当这种特殊的rustc代理模式运行时,持有跨进程锁以强制一次只修复一个构建目标,以避免竞态条件。
这确保了正确性,但代价是性能和在使rustc代理交互式方面的困难。
Glen实现了一个称为cargo-fixit的替代设计的概念证明。cargo fixit在循环中生成cargo check,确定哪些构建目标在给定传递中是安全修复的,然后应用建议。这使顶级程序负责应用哪些修复,使其更容易协调。它还允许移除锁定,并为交互式模式打开了大门。
Glen执行了各种基准测试来测试新方法的性能。在一些基准测试中,cargo fixit能够在几百毫秒内完成,而之前相同的任务花了cargo fix近一分钟!像往常一样,有权衡;新方法的代价是依赖树中较低包中的修复可能导致后来的包多次重建,减慢速度,因此也有基准测试中旧设计稍快。初始结果仍然非常令人鼓舞和印象深刻!
cargo-fixit上还有进一步的工作要做,以调查如何更好地优化它,以及它的界面在稳定之前应该是什么样子。我们感谢Glen在这个项目上的所有辛勤工作,我们希望有一天新设计将在Cargo中默认使用,为每个人带来更快、更灵活的lint建议修复!
原型化Cargo管道命令
贡献者: Vito Secona
导师: Cassaundra, Ed Page
最终报告
这个项目的目标是推进我们创建低级(“管道”)Cargo子命令的项目目标,以使其他工具更容易重用Cargo的部分。
Vito在cargo-plumbing crate中创建了几个管道命令的原型。想法是更好地了解管道命令应该是什么样子,以及从Cargo实现它们需要什么。Vito不得不在其中一些命令中做出妥协,以免被阻止对当前Cargo Rust API进行更改,他有助于记录了那些阻止程序。例如,管道命令将重新读取每个命令中的清单,而不是仅仅依赖用户传递的清单,防止调用者能够编辑它们以从Cargo获得特定行为,例如删除所有工作空间成员以允许基于每个包解析依赖项。
Vito做了很多工作,因为他实现了七个不同的管道子命令:
- locate-manifest
- read-manifest
- read-lockfile
- lock-dependencies
- write-lockfile
- resolve-features
- plan-build
作为未来的工作,我们希望处理一些关于如何将这些管道命令集成到Cargo本身内部的未解决问题,并扩展管道命令集。
我们感谢Vito在提高Cargo灵活性方面的所有工作。
结论
我们要感谢所有与我们一起参与2025年谷歌编程之夏的贡献者!这是一次爆炸,我们迫不及待想看看GSoC贡献者明年会提出哪些项目。我们还要感谢谷歌组织谷歌编程之夏计划,并允许我们今年有这么多项目。最后但同样重要的是,我们要感谢所有Rust导师,他们不知疲倦地帮助我们的贡献者完成他们的项目。没有你们,Rust GSoC将不可能。