我正在努力将我在The ? Operator Can Be Used in Functions That Return Result 章节中学到的知识应用到我的共享mpsc通道代码中。
下面是最小的代码:
use std::sync::{ mpsc, Arc, Mutex };
use std::error::Error;
fn main()
{
}
fn sh_rx_get( sh_rx : Arc< Mutex< mpsc::Receiver< usize > > > ) -> Result< usize, Box<dyn Error> >
{
let rx = sh_rx.lock()?;
let r = rx.try_recv()?;
Ok( r )
}我得到的错误是:
error[E0515]: cannot return value referencing function parameter `sh_rx`
--> src/main.rs:10:12
|
10 | let rx = sh_rx.lock()?;
| -----^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `sh_rx` is borrowed here在线playground。
有什么建议或提示吗?
发布于 2021-07-12 00:26:10
这个错误的原因是std::sync::Mutex::lock()返回了一个Result<MutexGuard<'_, T>, PoisonError<MutexGuard<'_, T>>>。正如您所看到的,该Result的错误情况具有借用原始锁的生存期(MutexGuard中的生存期'_ )。编译器试图告诉您,通过?返回错误将返回一个借用值- PoisonError<MutexGuard<'_, T>>> -该值是在此函数中创建的,并且仅有效;这将创建一个悬空引用,因此是一个编译错误。
当调用sh_rx.lock()时,会隐式创建有问题的本地借用(“当前函数拥有的数据”)。Rust将自动引用Arc sh_rx,然后从Arc取消对Mutex的引用,.lock()实际上是在Rust中定义的。
即使在错误情况下,lock()返回借用锁的值的原因是,如果另一个线程在持有锁时死机,则锁定失败;这可能意味着受锁保护的数据处于不一致的状态。PoisonError有一个获取锁的into_inner()方法,它需要借用原始锁才能获得锁。
您可以通过将PoisonError转换为不借用锁的其他类型来修复此问题。例如:
let rx = sh_rx.lock().map_err(|e| e.to_string())?;这之所以有效,是因为std中有一个From for Box,?-operator会自动使用它将String转换为函数返回的Box<dyn Error>。
https://stackoverflow.com/questions/68337877
复制相似问题