Concrete example of your first case: I have a project right now that uses rustix
and unix_path
in a no-std context. (It's a fully hosted environment; no-std is only being used to avoid a dependency on the C runtime.) Because rustix
and unix_path
are independent crates, neither of them provides an impl of
rustix::path::Arg
for unix_path::UnixPath
, and the orphan rule prevents me from providing one, which means I have to write path.as_unix_str().as_bytes()
every time I want to pass a path to a rustix function, which is often.
(It's my impression that this sort of thing is the most important reason why people want to relax the orphan rule. I could work around this with a newtype over UnixPath
, but getting its ergonomics to match UnixPath
's would be more work than continuing to type path.as_unix_str().as_bytes()
all over the place.)
This is not technically about the orphan rule, but it's a closely related possible language feature that would require us to solve many of the same problems: Sometimes a crate might wish to override the implementation of a trait by one of its dependencies. This same project provides a good example: In a no-std configuration, rustix's Display
impl for rustix::io::Errno
prints "os error <number>" for all errors, which is not exactly user friendly; I'd ideally like to override it with an impl that provides the usual human-readable error strings for at least the errno values that I expect to come up in normal operation. Again, this can be dealt with by using a wrapper struct, but at the expense of at least some ergonomics -- right now what I have is a local conversion trait that lets me write
writeln!(stderr, "failed to {}: {}", operation, err.msg())
when err
is an Errno, which is not bad but not as nice as
writeln!(stderr, "failed to {operation}: {err}")