The idea being that I do not care to know what failed in read_file_content, I will only handle the case where I get an error, no matter what it is.
My hope was to return Result<String, ()>, and use the ? operator to neatly propagate the error up and hope that it would be correctly converted. It is not converted, hence why you can see the empty struct with the implementations for each error that I am expecting.
conflicting implementations of trait `std::convert::From<Error>` for type `Error`:
note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T; // rustc(E0119)
conflicting implementations of trait `std::convert::From<()>` for type `()`:
note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T; // rustc(E0119)
It looks like a simple enough use case, and I am kind of surprised to be stuck on this? Am I doing something wrong here?
Since From already has one implementation that covers every single type, it's not possible to provide a completely generic implementation without conflicting with that existing one. However, you can restrict your implementation to types that implement the error::Error trait:
To be fair using Option is the simpliest way to write and express what I wanted, thanks!
I toyed with:
async fn read_file_content(path: &str) -> Result<String, ()> {
let raw = tokio::fs::read(path).await.or(Err(()))?;
let content = String::from_utf8(raw).or(Err(()))?;
Ok(content)
}
But it is plenty ugly... Really wished something more clean was possible in regards to Result.
I was using Result<String, Box<std::string::Error>> as a return before, but since I really didn't handle this error value I hoped I could get away from moving something onto the heap that I won't even look at...