在 Rust 中绕过专门化或我如何学会停止担忧并爱上函数指针

作者花费近一年用 Rust 开发和完善自己的 FAT 驱动,过去六个月因学校事务暂停项目,现在因该项目成为 GitHub 上星标最多的仓库而重新开始。

关于特化(Specialization)

  • 特化概念在 2015 年的RFC 1210中引入。
  • 以示例展示特化可让编译器意识到第二个impl比第一个更“特化”,代码可正常编译,且能根据对象实现的特质调用不同的do_something实现。
  • 但上述代码在 Rust 中不编译,原因是存在与生命周期相关的问题,虽有min-specialization特征但不稳定且作者不想处理安全问题。

为何需要特化

  • FAT 文件系统分为扇区,每次读写数据需将扇区加载到扇区缓冲区,修改后同步回文件系统。
  • 为实现可读写的FileSystem结构体,需在不同impl块中定义读写相关方法,但现有代码在Read+Seek`impl`块中无法写入存储,特化可解决此问题,但当前特化是不稳定特征。

尝试解决特化问题的过程

  • 尝试一:查看是否有人用宏实现了特化,找到 spez,但发现其在泛型函数中无用。
  • 尝试二:使用通用枚举和PhantomData,但遇到生命周期相关问题,最终放弃。
  • 最终解决方案:基于函数指针实现特化,通过两个构造函数分别创建只读和读写文件系统,在load_nth_sector函数中根据sync_fn字段是否有值来决定是否同步扇区缓冲区,从而“模拟”特化。

特化作为特征是否必要

  • 作者的解决方案特定于其用例,会增加结构体的开销,包括性能和内存方面,且实现较 sloppy,不稳定的specialization特征也存在生命周期问题。
  • 作者建议在特化稳定后使用,这样会更高效和干净。最后编辑(2025 年 7 月 26 日)表明作者的方法未达到预期效果,可查看后续文章。
阅读 186
0 条评论