I have many issues with the various Error types we define and how HttpsConnector ultimately just uses BoxError for its Service<Uri> error type, I'll try to summarize them here.
First, the BoxError, this makes it impossible to consume any more specific error type, as downcasting with the Error trait is always by reference.
Second, I keep confusing myself with boring::Error and boring::ssl::Error.
Third, the boring::ssl::HandshakeError is not fun to use for multiple reasons:
- the underlying I/O errors can be in two separate variants (
Failure and WouldBlock);
- it stores a
MidHandshakeSslStream<S> even in the Failure variant, even though you are obviously not supposed to do anything anymore with that stream given the handshake failed;
- given that second bullet point, it also doesn't make much sense for the
MidHandshakeSslStream<S> struct to keep around the error that interrupted the handshake, as that was expected and you just want to resume it;
- it has a variant
SetupFailure which feels out of place to me, shouldn't setup errors be completely contained in builders etc?
Fourth, tokio_boring::HandshakeError is as useful as BoxError given it doesn't let us access the boring::ssl::HandshakeError it wraps directly, so that's one more layer of hoops to go through to find, say, I/O errors.
Fifth, even if tokio_boring::HandshakeError let us access its inner boring::ssl::HandshakeError, that would still be a bit of a bother to use, as we know tokio_boring would never return a WouldBlock error but we would still need an arm for that in our code.
I have many issues with the various
Errortypes we define and howHttpsConnectorultimately just usesBoxErrorfor itsService<Uri>error type, I'll try to summarize them here.First, the
BoxError, this makes it impossible to consume any more specific error type, as downcasting with theErrortrait is always by reference.Second, I keep confusing myself with
boring::Errorandboring::ssl::Error.Third, the
boring::ssl::HandshakeErroris not fun to use for multiple reasons:FailureandWouldBlock);MidHandshakeSslStream<S>even in theFailurevariant, even though you are obviously not supposed to do anything anymore with that stream given the handshake failed;MidHandshakeSslStream<S>struct to keep around the error that interrupted the handshake, as that was expected and you just want to resume it;SetupFailurewhich feels out of place to me, shouldn't setup errors be completely contained in builders etc?Fourth,
tokio_boring::HandshakeErroris as useful asBoxErrorgiven it doesn't let us access theboring::ssl::HandshakeErrorit wraps directly, so that's one more layer of hoops to go through to find, say, I/O errors.Fifth, even if
tokio_boring::HandshakeErrorlet us access its innerboring::ssl::HandshakeError, that would still be a bit of a bother to use, as we knowtokio_boringwould never return aWouldBlockerror but we would still need an arm for that in our code.