error-chain icon indicating copy to clipboard operation
error-chain copied to clipboard

Consider adding support for Futures crate

Open psFried opened this issue 8 years ago • 14 comments
trafficstars

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?

psFried avatar Dec 03 '16 23:12 psFried

Maybe simply impl [ResultExt](https://docs.rs/error-chain/0.7.1/error_chain/example_generated/trait.ResultExt.html) for Future?

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

@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.

psFried avatar Dec 03 '16 23:12 psFried

Just thinking that in the future we could use Carrier, when it's stabilized. It would apply to Future, Result and Option.

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

It will definitively be an optional feature. Do you want to try?

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

Good idea about using the Carrier trait once it's stabilized. Yeah, I can take a stab at it and send a PR over.

psFried avatar Dec 03 '16 23:12 psFried

In fact, can't it be implemented in future?

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

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?

psFried avatar Dec 03 '16 23:12 psFried

My bad, my change was reverted few days ago ;)

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

BTW, could Future implement Carrier?

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

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.

psFried avatar Dec 03 '16 23:12 psFried

Do you have an example of code where you would like to use error-chain?

Yamakaky avatar Dec 03 '16 23:12 Yamakaky

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.

psFried avatar Dec 04 '16 00:12 psFried

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.

alexcrichton avatar Feb 17 '17 16:02 alexcrichton

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

sezaru avatar May 07 '17 04:05 sezaru