作者自 2016 年起将 Rust 用于业余项目,2021 年起从事 Rust 专业工作,自认为对 Rust 较了解,熟悉 Rust 类型系统的常见限制及解决方法。本文将介绍工作中遇到的 Rust 借用检查器的四个令人惊讶的限制:
- 检查未考虑匹配和返回:在哈希表中查找值时,若要根据值是否存在做不同操作,获取共享引用时没问题,但获取独占引用时会报错,因为借用检查器有限的流分析能力,导致第一次获取借用后整个函数都认为被借用,解决方法是进行不必要的检查和查找。
- 异步是一种痛苦:想为自定义结构体
MyVec
提供一个方法,能在每个元素上调用用户提供的回调函数,包括异步代码,但目前无法在 Rust 中表达所需的类型签名,即使添加了use<'a>
语法和通用关联类型也不行。 FnMut
不允许重新借用捕获的值:在处理异步回调时,当传递一个实际捕获了值的回调函数时会出错,因为async_for_all
方法的签名不够通用,FnMut
的设计导致输出类型不能依赖于self
生命周期,而&mut
引用是唯一需要重新借用的情况。- 发送检查器不了解控制流:在工作中写的一段代码,根据条件决定是否持有锁并进行不同操作,在主任务中运行没问题,但将其移到单独任务时,由于编译器不进行控制流分析,未来值被标记为不是
Send
,解决方法是将锁放入显式作用域,并复制if
条件,将else
分支移到作用域外。
结论:Rust 的类型系统在典型情况下工作良好,但仍有偶尔的惊喜,由于不可判定性问题,静态类型系统无法允许所有有效的程序,但编程语言可以做得足够好,使这不是一个实际问题。文中提到的四个问题中,前两个相对容易解决,后两个则更具复杂性。异步 Rust 与经典的直线 Rust 相比表现不佳,这是令人遗憾的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。