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 isOn success, we return
(). On failure, we give ownership of theTback to the caller.In your case, the return type is
Result<(), Mutex<Coms>>.Now,
anyhow::Erroris a really neat type. It's capable of storing any error condition, but not any type. It can't store ani32, or a lot of other random types. It can only store types that implementError, andMutexdoes not implement that trait.You can't convert a
Mutex<Coms>into aanyhow::Error.You can explicitly discard it if you don't care about the error condition.
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 usingmap_errand then use?on that to convert toanyhow::Error. You can panic on failed sets, usingexpect.Or, of course, you can just straight-up pattern match on the result and do something custom with the original mutex.