I'm trying to compile something like the following:
use anyhow::Result;
use std::sync::{mpsc, Mutex, OnceLock};
use std::cell::Cell;
use std::fmt;
static COMS: OnceLock<Mutex<Coms>> = OnceLock::new();
struct Coms {
tx: Cell<Option<mpsc::Sender<Msg>>>,
rx: Cell<Option<mpsc::Receiver<Msg>>>,
}
enum Msg {}
fn bar() -> Result<()> {
let (tx, rx) = mpsc::channel();
COMS.set(
Mutex::new(
Coms {
tx: Cell::new(Some(tx)),
rx: Cell::new(Some(rx)),
}
)
);
//)?;
Ok(())
}
fn main() {
let _ = bar();
}
I get an expected warning about an unused Result:
warning: unused `Result` that must be used
--> src/main.rs:17:5
|
17 | / COMS.set(
18 | | Mutex::new(
19 | | Coms {
20 | | tx: Cell::new(Some(tx)),
... |
23 | | )
24 | | );
| |_____^
However, if I swap out the line with the );
for a )?;
, I get an error like:
error[E0277]: the trait bound `Mutex<Coms>: std::error::Error` is not satisfied
--> src/main.rs:25:6
|
25 | )?;
| ^ the trait `std::error::Error` is not implemented for `Mutex<Coms>`
|
The documentation for OnceLock::set()
says it returns a Result
, so why does it look like it is returning a Mutex<Coms>
in the second case?
Why does rustc seem to think this is a Result
in the first case (expected) and a Mutex<Coms>
in the second case? This is using rustc 1.71.0
. I must be misunderstanding what the compiler is trying to tell me.
It is a Result
. Specifically, the signature of that function is
pub fn set(&self, value: T) -> Result<(), T>
On success, we return ()
. On failure, we give ownership of the T
back to the caller.
In your case, the return type is Result<(), Mutex<Coms>>
.
Now, anyhow::Error
is a really neat type. It's capable of storing any error condition, but not any type. It can't store an i32
, or a lot of other random types. It can only store types that implement Error
, and Mutex
does not implement that trait.
You can't convert a Mutex<Coms>
into a anyhow::Error
.
You can explicitly discard it if you don't care about the error condition.
let _ = COMS.set(...);
This is a loud assertion to Rust saying "Yes, we might get Err
. I don't care; ignore it".
You can replace the Mutex<Coms>
with an actual error type using map_err
and then use ?
on that to convert to anyhow::Error
. You can panic on failed sets, using expect
.
Or, of course, you can just straight-up pattern match on the result and do something custom with the original mutex.