rust-libp2p icon indicating copy to clipboard operation
rust-libp2p copied to clipboard

Refactoring: Drop custom `Either` types where possible

Open thomaseizinger opened this issue 3 years ago • 5 comments

Description

We have a lot of custom Either types within libp2p-core, some of which (I think) could go away by implementing our traits directly on the Either type that we are already depending on.

Motivation

Less code to maintain.

Are you planning to do it yourself in a pull request?

No / Maybe. Could be a good first issue. What do you think @mxinden?

thomaseizinger avatar May 16 '22 11:05 thomaseizinger

Sounds good to me. Also, should we be using either::Either or futures::future::Either or both?

mxinden avatar May 17 '22 08:05 mxinden

Sounds good to me. Also, should we be using either::Either or futures::future::Either or both?

I am not sure how well maintained either::Either is but feels like the more appropriate one, given that Future is part of std now?

I've had a brief look and for example the Error impl in either::Either is not overriding all methods so it may need a bit of upstream work until we can completely replace our types.

I think as part of this ticket, one would need to do a bit more research to see if we can drop future::Either for example. Would be interesting to know, why they have their own Either type in the first place.

thomaseizinger avatar May 17 '22 12:05 thomaseizinger

examining it naively the future::Either could be dropped as it seems to serve as a convenience enum type, which could be replaced by what you mentioned earlier by implementing our traits directly on the Either type or implementing IntoFuture to be awaited.

maschad avatar May 19 '22 17:05 maschad

I've had a brief look and for example the Error impl in either::Either is not overriding all methods so it may need a bit of upstream work until we can completely replace our types.

This is fixed now: https://github.com/bluss/either/pull/69

There is also a new release coming: https://github.com/bluss/either/pull/73

thomaseizinger avatar Jun 29 '22 07:06 thomaseizinger

I've opened an issue regarding pin projection which is another blocker for some of our Either use cases: https://github.com/bluss/either/issues/76

thomaseizinger avatar Jul 25 '22 08:07 thomaseizinger

I opened an issue with either to see if we can get AsyncRead + AsyncWrite traits. Then we could drop the EitherOutput type: https://github.com/bluss/either/issues/79

thomaseizinger avatar Jan 11 '23 04:01 thomaseizinger

I opened an issue with either to see if we can get AsyncRead + AsyncWrite traits. Then we could drop the EitherOutput type: bluss/either#79

Update: As suggested in the linked issue, we could simply use the futures::Either type for all cases where we need implementations of AsyncRead etc.

I think that is a sensible way forward. Using the same type everywhere would be better but using two already existing ones is already an improvement over defining our own types in my opinion.

thomaseizinger avatar Jan 13 '23 00:01 thomaseizinger

I opened an issue with either to see if we can get AsyncRead + AsyncWrite traits. Then we could drop the EitherOutput type: bluss/either#79

Update: As suggested in the linked issue, we could simply use the futures::Either type for all cases where we need implementations of AsyncRead etc.

I think that is a sensible way forward. Using the same type everywhere would be better but using two already existing ones is already an improvement over defining our own types in my opinion.

Unfortunately, this doesn't quite work.

  1. Our EitherFuture type only works on TryFutures and directly transposes the result.
  2. We use our EitherFuture type in multiple places. In some of them, the resulting Output should be an Either that implements futures traits and in some it should be the regular Either.
  3. The futures::Either type implements Future such that both futures need to evaluate to the same type which is a bit silly IMO and probably the reason we have our own type.

The bottom line is that I think we should convince either that they should provide a Future etc implementation that doesn't try to be clever but simply sets all associated types like Future::Output and Stream::Item to Either.

thomaseizinger avatar Jan 17 '23 13:01 thomaseizinger

The bottom line is that I think we should convince either that they should provide a Future etc implementation that doesn't try to be clever but simply sets all associated types like Future::Output and Stream::Item to Either.

That is also not possible because they already implement Future in the exact same way as futures::Either. Unfortunately, this means we are stuck with a custom EitherFuture type that behaves the way we need it. The good news is that we might only need it for SelectUpgrade if we end up doing https://github.com/libp2p/rust-libp2p/issues/3347.

thomaseizinger avatar Jan 18 '23 13:01 thomaseizinger

EitherFuture is here to stay for a while so I am considering this to be completed because everything that is actionable has been done.

thomaseizinger avatar May 08 '23 09:05 thomaseizinger