1 个不稳定版本
使用旧的 Rust 2015
0.1.0 | 2022年2月8日 |
---|
#6 in #workaround
12KB
Polonius_workaround
此包提供了简单且逻辑安全的 API,用于解决 Polonius 将解决的借用检查器限制的不安全解决方案。
许可证
MIT
lib.rs
:
此包提供了 API 来解决由当前 Rust 借用检查限制引起的借用检查错误。存在下一个版本的 Rust 借用检查器,称为 Polonius,它应该消除此类限制,但它始终不稳定,没有当前的稳定计划。而且,在稳定 Rust 中,通常只能通过使用不安全代码来绕过这些限制,这可能导致某些形式的回归。但是,对于这样简单的事情,被要求使用不安全代码是令人烦恼的,而且很容易出错,更不用说它只是一个延迟的炸弹,等待着某些粗心的重构来释放它。
所有功能都通过 PoloniusExt
扩展 trait 提供。它有 3 个方法
try_get_with
/try_get_mut_with
适用于需要返回共享/可变引用的简单情况。它应该正常工作,在大多数情况下就足够了。但有时你需要返回的不是引用,而是包含引用的另一种类型。这时你需要try_get_with2
它允许你返回任何包含引用的类型,但由于 Rust 类型推断中的 HRTB 故障,它的使用有点令人烦恼。有关更多详细信息,请参阅其文档。
据作者所知,它可以解决任何类型的借用检查器问题,这些问题将由 Polonius 解决。尽管你仍然需要足够自信,知道你的代码实际上是正确的,只是没有被当前的借用检查器接受。因此,尽管使用此包你不再需要 Polonius,但它仍然是一般上很好的东西。
代码从 Rust 1.0 开始编译,但 try_get_with2
实际上只能在 Rust 1.41 及以上版本中使用。
以下是一个实际示例,没有显著的性能回归或不安全代码,你无法解决这个问题。
trait LinkedListExt<T> {
fn find_or_create<F, C>(&mut self, predicate: F, create: C) -> &mut T
where
F: FnMut(&T) -> bool,
C: FnMut() -> T;
}
impl<T: 'static> LinkedListExt<T> for LinkedList<T> {
fn find_or_create<F, C>(&mut self, mut predicate: F, mut create: C) -> &mut T
where
F: FnMut(&T) -> bool,
C: FnMut() -> T,
{
if let Some(x) = self.iter_mut().find(|e| predicate(&*e)){
return x;
}
self.push_back(create());
self.back_mut().unwrap()
}
}
现在,使用此包,你只需将两个分支包裹在闭包中,然后调用 try_get_mut_with
,然后就可以了
impl<T: 'static> LinkedListExt<T> for LinkedList<T> {
fn find_or_create<F, C>(&mut self, mut predicate: F, mut create: C) -> &mut T
where
F: FnMut(&T) -> bool,
C: FnMut() -> T,
{
self.try_get_mut_with(|x| x.iter_mut().find(|e| predicate(&*e)))
.unwrap_or_else(|x| {
x.push_back(create());
x.back_mut().unwrap()
})
}
}