error-chain
error-chain copied to clipboard
Consider adding support for Futures crate
I've been playing around with Futures and Tokio lately, and one of the things that's been a major pain point has been dealing with errors from Futures. I think it would be really nice to be able to call chain_err on a Future. Currently, the Future trait defines a map_err function, which isn't to terribly far off. It's just a lot more verbose since the conversion between error types has to be done manually. Any thoughts?
Maybe simply impl [ResultExt](https://docs.rs/error-chain/0.7.1/error_chain/example_generated/trait.ResultExt.html) for Future?
@Yamakaky Yeah, exactly. It's probably easy enough to do that it wouldn't be all that bad to just add that boilerplate into every project that uses Futures, but I'm wondering if Futures is going to be popular enough to warrant just adding support to the error_chain crate maybe as an optional feature.
Just thinking that in the future we could use Carrier, when it's stabilized. It would apply to Future, Result and Option.
It will definitively be an optional feature. Do you want to try?
Good idea about using the Carrier trait once it's stabilized. Yeah, I can take a stab at it and send a PR over.
In fact, can't it be implemented in future?
You mean in the futures crate? I don't think it could really be implemented there since the trait is defined in the macro, right?
My bad, my change was reverted few days ago ;)
BTW, could Future implement Carrier?
5 minutes ago, I didn't see any problems with that, but now I've realized that it probably can't work. The problem I see is that a Future doesn't itself represent a result, so the ? operator really wouldn't make any sense. You don't know whether the future represents a success or failure until after it's been completed, at which point it just returns a Result.
Do you have an example of code where you would like to use error-chain?
Sure. In the example, the methods in tokio_core::io all return Futures where the error type is std::io::Error, but my_future_fn returns a Future with an associated error type of, MyError.
let future = tokio_core::net::TcpStream::connect(&addr, &reactor.handle()).map_err(|err| {
format!("error creating connection: {:?}", err)
}).and_then(|tcp_stream| {
my_future_fn().map_err(|err| {
format!("Error in my_future_fn: {:?}", err)
}).and_then(|my_value| {
tokio_core::io::write_all(tcp_stream, my_value)
})
});
let result: Result<(TcpStream, Vec<u8>), String> = reactor.run(future);
In that example, both the io errors and the custom error types are being converted to strings since they need to be the same type in order for the chained calls to and_then to work. A better way of doing this would of course be to convert them to a better common error type than String, but you get the picture. It just ends up being verbose having to do all the conversions manually in map_err calls.
FWIW I wrote a small helper to add the chain_err method to futures, but there's likely other cool integration that can happen as well.
Hello, I've made some changes to @alexcrichton helper to work with futures_cpupool::CpuPool (since CpuPool::spawn needs the future to have Send trait implemented and for the ones I was testing it was failing.
Also, I've made a macro future_chain! which works like error_chain! (since I almost CTRL+C CTRL+V it) but only supports types block.
With it you can just use future_chain!{} after error_chain!{} to generate a special FutureChain type that works with error-chain structure.
All the code is in this link: https://play.rust-lang.org/?gist=0df6f758e0f109fe64ad83cbf1ea7c2c&version=stable&backtrace=0 Note that Rust playground doesn't support crates, so you will need to create a local cargo projeto to it and add
[dependencies]
error-chain = "0.10.0"
futures = "0.1.9"
futures-cpupool = "0.1"
to it.
I hope this helps someone