Executor bounds on client and server types publicly nameable, while still preserving the ability to change internal spawning needs.
hyper's client and server types require a
hyper::rt::Executor to spawn some related background tasks.
There's two conflicting requirements for the executor:
- The internal types that are spawned must be provided to the
Executor<InternalFuture>), so that the
Sendiness can be propagated. This allows users to have
!Send futures and bodies as long as they provide an
Executor that can spawn them.
- The internal types expose some of the private architecture, so being able to name them makes it impossible to refactor in the future. Being able to exhaustively name them would prevent us from spawning new background tasks as features are developed.
So far, we have solved this by using privately-public traits, which are blanketly implemented for all generic executors. This allows us to change the types internally, and as long as a user provides a type that is
impl<F: Future> Executor<F> for MyExec, it just works.
But it has some annoying problems.
- It's not possible to build functions or types on top, since in another crate, you can't write
E: Executor<CantNameMe>, nor
E: hyper::unnameable::ConnStreamExec (see #2051; https://github.com/hyperium/hyper-util/pull/11#discussion_r1044221053).
- The bounds are confusing in the documentation (for example).
Define public trait aliases that are sealed, but can be named externally, and have documentation showing how to provide a
Executor to match the bounds, and how to express the bounds in your own API.
For example: define
hyper::rt::bounds::ServerConnHttp2Exec, which is a public trait.
This allows us to continue to not expose the actual internal types, and also to extend the trait to be represent spawning other tasks if need be.
S-feature E-medium A-rt