how to convert anyhow error to std error? - rust

I am new to anyhow and I would like to know if there is a way to convert anyhow error to std error
code
fn m() {
let a: anyhow::Result<String> = Ok("".into());
n(a);
}
fn n(r: std::result::Result<String, impl std::error::Error>) {
println!("{:?}", r);
}
error msg
error[E0277]: the trait bound `anyhow::Error: std::error::Error` is not satisfied
--> src\main.rs:82:7
|
82 | n(a);
| - ^ the trait `std::error::Error` is not implemented for `anyhow::Error`
| |
| required by a bound introduced by this call

Use the Deref or AsRef impl:
match a {
Ok(v) => n(Ok::<_, &dyn std::error::Error>(v)),
Err(e) => n(Err::<_, &dyn std::error::Error>(e.as_ref())),
}
// Or
match a {
Ok(v) => n(Ok::<_, &dyn std::error::Error>(v)),
Err(e) => n(Err::<_, &dyn std::error::Error>(&*e)),
}

Related

How to return an iterator for single or multiple values in enum

Consider the following code:
struct MediaKind;
struct OtherFields;
enum Media {
Single(MediaKind),
Group(Vec<MediaKind>, OtherFields),
}
impl Media {
fn iter(&self) -> impl Iterator<Item = &MediaKind> {
match self {
Self::Single(media) => [media].iter(),
Self::Group(media_vec, _) => media_vec.iter(),
}
}
}
Compile error:
error[E0308]: `match` arms have incompatible types
--> src/lib.rs:13:42
|
11 | / match self {
12 | | Self::Single(media) => [media].iter(),
| | -------------- this is found to be of type `std::slice::Iter<'_, &MediaKind>`
13 | | Self::Group(media_vec, _) => media_vec.iter(),
| | ^^^^^^^^^^^^^^^^ expected `&MediaKind`, found struct `MediaKind`
14 | | }
| |_________- `match` arms have incompatible types
|
= note: expected struct `std::slice::Iter<'_, &MediaKind>`
found struct `std::slice::Iter<'_, MediaKind>`
Because the Group arm may contain additional fields, replacing this entire enum with a Vec is not a preferred solution.
I have tried either crate to solve the problem in the following way:
fn iter(&self) -> impl Iterator<Item = &MediaKind> {
use either::*;
match self {
Self::Single(media) => Left([media].into_iter()),
Self::Group(media_vec, _) => Right(media_vec.iter()),
}
}
But I'm wondering if it's possible to fix it without depending on an external crate.
> Link to playground
In this case, because one case is a slice iterator and the other is one element, you can use a trick: std::slice::from_ref():
fn iter(&self) -> impl Iterator<Item = &MediaKind> {
match self {
Self::Single(media) => std::slice::from_ref(media).iter(),
Self::Group(media_vec, _) => media_vec.iter(),
}
}
Playground.

How to pass a function as parameter for thread?

I'm a new rustacean and I try to pass a function as argument in another function in order to create threads with the function pass as argument.
Here the code:
use std::os::unix::net::{UnixListener, UnixStream};
use std::thread;
use std::io::Read;
use anyhow::Context;
pub struct SocketServer {
path: String,
listener: UnixListener,
}
impl SocketServer {
pub fn new(path: &str) -> anyhow::Result<SocketServer>{
if std::fs::metadata(path).is_ok() {
println!("A socket is already present. Deleting...");
std::fs::remove_file(path).with_context(|| {
format!("could not delete previous socket at {:?}", path)
})?;
}
let socket_listener =
UnixListener::bind(path).context("Could not create the unix socket")?;
let path = path.to_string();
Ok(SocketServer{ path, listener: socket_listener })
}
pub fn start(&self, f: &dyn Fn(UnixStream)) -> anyhow::Result<()>{
for stream in self.listener.incoming() {
match stream {
Ok(stream) => {
thread::spawn(||f(stream));
}
Err(err) => {break;}
}
}
Ok(())
}
}
pub fn handle_stream(mut unix_stream: UnixStream) -> anyhow::Result<()> {
let mut message = String::new();
unix_stream
.read_to_string(&mut message)
.context("Failed at reading the unix stream")?;
println!("We received this message: {}", message);
Ok(())
}
Here the error I get when in try to compile:
error[E0277]: `dyn Fn(UnixStream)` cannot be shared between threads safely
--> src/socket.rs:34:35
|
34 | thread::spawn(||f(stream));
| ------------- ^^^^^^^^^^^ `dyn Fn(UnixStream)` cannot be shared between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `dyn Fn(UnixStream)`
= note: required for `&dyn Fn(UnixStream)` to implement `Send`
I got some information in the Rust book but I still don't understand which function need to implement what.
Can you give me some hints? (Advice on other parts are welcome too)
I tried to remove closure but it goes to another error:
error[E0277]: expected a `FnOnce<()>` closure, found `()`
--> src/socket.rs:34:35
|
34 | thread::spawn(f(stream));
| ------------- ^^^^^^^^^ expected an `FnOnce<()>` closure, found `()`
| |
| required by a bound introduced by this call
|
= help: the trait `FnOnce<()>` is not implemented for `()`
= note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `spawn`
--> /rust/lib/rustlib/src/rust/library/std/src/thread/mod.rs:661:8
|
661 | F: FnOnce() -> T,
| ^^^^^^^^^^^^^ required by this bound in `spawn`
Is there a reason you need a dyn Fn?
The easiest is probably to accept a impl Fn(UnixStream) + Send + Clone + 'static instead
pub fn start<F>(&self, f: F) -> anyhow::Result<()>
where
F: Fn(UnixStream) + Send + Clone + 'static,
{
for stream in self.listener.incoming() {
let f = f.clone();
match stream {
Ok(stream) => {
thread::spawn(move || f(stream));
}
Err(err) => break,
}
}
Ok(())
}
The dyn Fn() may capture things (such as Rcs) that are unsafe to share between threads. So you need to mark it Sync:
pub fn start(&self, f: &(dyn Fn(UnixStream) + Sync)) -> anyhow::Result<()> {
Now you'll get another error:
error[E0521]: borrowed data escapes outside of associated function
--> src/lib.rs:34:21
|
30 | pub fn start(&self, f: &(dyn Fn(UnixStream) + Sync)) -> anyhow::Result<()> {
| - - let's call the lifetime of this reference `'1`
| |
| `f` is a reference that is only valid in the associated function body
...
34 | thread::spawn(|| f(stream));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| `f` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
Because the function's captured data may be dropped before the thread exits, causing use after free. The easiest solution is to use Arc:
pub fn start(&self, f: Arc<dyn Fn(UnixStream) + Sync + Send>) -> anyhow::Result<()> {
for stream in self.listener.incoming() {
match stream {
Ok(stream) => {
let f = Arc::clone(&f);
thread::spawn(move || f(stream));
}
Err(err) => {
break;
}
}
}
Ok(())
}
(You also need a Send bound).

Unable to infer type in let match with a trait [duplicate]

This question already has an answer here:
Return Result<Box<dyn Trait>> in a match
(1 answer)
Closed 6 months ago.
I have an operation that I'd like to err out on invalid input, otherwise create one of two structs which implement a trait. I'm sure this isn't a shortcoming of the compiler but rather my poor understanding of the type system and I'm looking for some input. This is a simplified version of my code but the core issue remains.
pub trait Action { ... }
pub struct TaxonomySpotSearch { ... }
impl Action for TaxonomySpotSearch { ... }
pub struct SavedSearch { ... }
impl Action for SavedSearch { ... }
fn do_something() -> Result<i32, ArgError> {
let foo: Box<dyn Action> = match Some(1) {
Some(0) => Ok(Box::new(TaxonomySpotSearch::new())),
Some(1) => Ok(Box::new(SavedSpotSearch::new())),
_ => Err(ArgError::NoSubCommand)
}?;
Ok(...)
}
However, I'm getting the classic E0308 "match arms have incompatible types" error where the compiler is inferring the type of foo as the return value of the first match arm.
error[E0308]: `match` arms have incompatible types
--> src/main.rs:127:20
|
125 | let foo: Box<dyn Action> = match Some(1) {
| ________________________________-
126 | | Some(0) => Ok(Box::new(TaxonomySpotSearch::new())),
| | --------------------------------------- this is found to be of type `Result<Box<TaxonomySpotSearch>, _>`
127 | | Some(1) => Ok(Box::new(SavedSpotSearch::new())),
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `TaxonomySpotSearch`, found struct `SavedSpotSearch`
128 | | _ => Err(ArgError::NoSubCommand)
129 | | }?;
| |_____- `match` arms have incompatible types
|
= note: expected enum `Result<Box<TaxonomySpotSearch>, _>`
found enum `Result<Box<SavedSpotSearch>, _>`
Am I doing something wrong or is this really a limitation of the type system? I would expect the addition of the explicit type annotation to resolve this, yet here I am.
The Rust compiler doesn't understand that you want them both to be Box<dyn Action>, it takes them as the real type they are.
You need to tell that to the Rust compiler explicitely:
pub trait Action {}
pub struct TaxonomySpotSearch {}
impl Action for TaxonomySpotSearch {}
pub struct SavedSearch {}
impl Action for SavedSearch {}
enum ArgError {
NoSubCommand,
}
fn do_something() -> Result<(), ArgError> {
let foo: Box<dyn Action> = match Some(1) {
Some(0) => Ok(Box::new(TaxonomySpotSearch {}) as Box<dyn Action>),
Some(1) => Ok(Box::new(SavedSearch {}) as Box<dyn Action>),
_ => Err(ArgError::NoSubCommand),
}?;
Ok(())
}

Can I return std::result::Result from a Future?

I'm trying to understand Rust futures. I did:
#[derive(Debug)]
pub enum ClientError {
UrlParseError((String, String)),
BindError
}
pub async fn connect(addr: std::net::SocketAddr) -> impl std::future::Future<Output = std::result::Result<(), ClientError>> {
let listener = async_std::net::TcpListener::bind(&addr).await;
let listener = match listener {
Ok(listener) => listener,
Err(_) => return Err(ClientError::BindError)
};
//Ok(())
std::future::ready(Ok(()))
}
I get
error[E0277]: `std::result::Result<_, ClientError>` is not a future
--> src/lib.rs:7:53
|
7 | pub async fn connect(addr: std::net::SocketAddr) -> impl std::future::Future<Output = std::result::Result<(), ClientError>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::result::Result<_, ClientError>` is not a future
|
= help: the trait `Future` is not implemented for `std::result::Result<_, ClientError>`
error[E0308]: mismatched types
--> src/lib.rs:14:5
|
14 | std::future::ready(Ok(()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `std::future::Ready`
|
= note: expected type `std::result::Result<_, ClientError>`
found struct `std::future::Ready<std::result::Result<(), _>>`
note: return type inferred to be `std::result::Result<_, ClientError>` here
--> src/lib.rs:11:26
|
11 | Err(_) => return Err(ClientError::BindError)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
I honestly don't know what is wrong. I cannot return a Result from a future?
How can I fix this?
I tried returning just Ok(()) and I don't get the second error
Is this works for you?
#[derive(Debug)]
pub enum ClientError {
UrlParseError((String, String)),
BindError
}
pub async fn connect(addr: std::net::SocketAddr) -> Result<(), ClientError> {
let listener = async_std::net::TcpListener::bind(&addr)
.await
.or(Err(ClientError::BindError))?
;
Ok(())
}

Closure as generic return `impl FnMut(T)`

I've implemented callback_list_stream generically, but I can't seem to use it in a specialized way. The code works if I copy/paste the code per T.
use futures::channel::mpsc::Receiver;
use futures::{channel::mpsc::channel};
use libpulse_binding::{
callbacks::ListResult,
context::introspect::{SinkInfo, SinkPortInfo, SourceInfo, SourcePortInfo},
};
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Waker};
use std::{borrow::Cow, boxed::Box};
pub fn callback_list_stream<T: MakeOwned >() -> (impl FnMut(ListResult<&T>), Receiver<<T as MakeOwned>::Owned>) {
let (mut sender, recv) = channel(1024); // TODO channel size?
let cb = {
move |c: ListResult<&T>| match c {
ListResult::Item(it) => match sender.try_send(it.make_owned()) {
Ok(_) => (),
Err(err) => eprintln!("Failed to send message {:?}", err),
},
ListResult::End => sender.disconnect(),
ListResult::Error => (), // TODO
}
};
(cb, recv)
}
pub fn foo() -> (
impl FnMut(ListResult<&SourceInfo<'_>>),
Receiver<SourceInfo<'static>>
) {
callback_list_stream()
}
The compiler complains:
error[E0277]: expected a `std::ops::FnMut<(pulse::callbacks::ListResult<&pulse::context::introspect::SourceInfo<'_>>,)>` closure, found `impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>`
--> src/futuristic_pulse/callback_future.rs:230:5
|
230 | impl FnMut(ListResult<&SourceInfo<'_>>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut<(pulse::callbacks::ListResult<&pulse::context::introspect::SourceInfo<'_>>,)>` closure, found `impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>`
...
233 | callback_list_stream()
| ---------------------- this returned value is of type `(impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>, futures_channel::mpsc::Receiver<pulse::context::introspect::SourceInfo<'static>>)`
|
= help: the trait `for<'r, 's> std::ops::FnMut<(pulse::callbacks::ListResult<&'r pulse::context::introspect::SourceInfo<'s>>,)>` is not implemented for `impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>`
= note: the return type of a function must have a statically known size
error[E0271]: type mismatch resolving `for<'r, 's> <impl for<'t0> std::ops::FnMut<(pulse::callbacks::ListResult<&'t0 _>,)> as std::ops::FnOnce<(pulse::callbacks::ListResult<&'r pulse::context::introspect::SourceInfo<'s>>,)>>::Output == ()`
--> src/futuristic_pulse/callback_future.rs:230:5
|
230 | impl FnMut(ListResult<&SourceInfo<'_>>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
|
= note: the return type of a function must have a statically known size
I believe that need to add a constrain on the lifetime of the inner SourceInfo data to the original reference:
pub fn foo<'a, 'b>() -> (
impl FnMut(ListResult<&'a SourceInfo<'b>>),
Receiver<SourceInfo<'static>>,
) where 'b : 'a {
let (cb, recv) = callback_list_stream();
(cb, recv)
}

Resources