- Feature Name:
io_error_sync
- Start Date: 2015-04-11
- RFC PR: rust-lang/rfcs#1057
- Rust Issue: rust-lang/rust#24133
Summary
Add the Sync
bound to io::Error
by requiring that any wrapped custom errors
also conform to Sync
in addition to error::Error + Send
.
Motivation
Adding the Sync
bound to io::Error
has 3 primary benefits:
- Values that contain
io::Error
s will be able to beSync
- Perhaps more importantly,
io::Error
will be able to be stored in anArc
- By using the above, a cloneable wrapper can be created that shares an
io::Error
using anArc
in order to simulate the old behavior of being able to clone anio::Error
.
Detailed design
The only thing keeping io::Error
from being Sync
today is the wrapped custom
error type Box<error::Error+Send>
. Changing this to
Box<error::Error+Send+Sync>
and adding the Sync
bound to io::Error::new()
is sufficient to make io::Error
be Sync
. In addition, the relevant
convert::From
impls that convert to Box<error::Error+Send>
will be updated
to convert to Box<error::Error+Send+Sync>
instead.
Drawbacks
The only downside to this change is it means any types that conform to
error::Error
and are Send
but not Sync
will no longer be able to be
wrapped in an io::Error
. It’s unclear if there’s any types in the standard
library that will be impacted by this. Looking through the list of
implementors for error::Error
, here’s all of the types that may be
affected:
io::IntoInnerError
: This type is onlySync
if the underlying buffered writer instance isSync
. I can’t be sure, but I don’t believe we have any writers that areSend
but notSync
. In addition, this type has aFrom
impl that converts it toio::Error
even if the writer is notSend
.sync::mpsc::SendError
: This type is onlySync
if the wrapped valueT
isSync
. This is of course also true forSend
. I’m not sure if anyone is relying on the ability to wrap aSendError
in anio::Error
.sync::mpsc::TrySendError
: Same situation asSendError
.sync::PoisonError
: This type is already not compatible withio::Error
because it wraps mutex guards (such assync::MutexGuard
) which are notSend
.sync::TryLockError
: Same situation asPoisonError
.
So the only real question is about sync::mpsc::SendError
. If anyone is relying
on the ability to convert that into an io::Error
a From
impl could be
added that returns an io::Error
that is indistinguishable from a wrapped
SendError
.
Alternatives
Don’t do this. Not adding the Sync
bound to io::Error
means io::Error
s
cannot be stored in an Arc
and types that contain an io::Error
cannot be
Sync
.
We should also consider whether we should go a step further and change
io::Error
to use Arc
instead of Box
internally. This would let us restore
the Clone
impl for io::Error
.
Unresolved questions
Should we add the From
impl for SendError
? There is no code in the rust
project that relies on SendError
being converted to io::Error
, and I’m
inclined to think it’s unlikely for anyone to be relying on that, but I don’t
know if there are any third-party crates that will be affected.