-
Notifications
You must be signed in to change notification settings - Fork 24
Description
Proposal
Problem statement
It would be great for OS-independent parts of std::io to be usable in alloc.
Motivating examples or use cases
std::io is a very useful abstraction, but unfortunately it is not available in no_std contexts, even though most of std::io do not depend directly on the underlying OS.
Today, OS-independent crates that use IO traits have the choice between using an alternative but incompatible implementation, such as embedded-io and not supporting no_std.
Solution sketch
The idea of this proposal is to move all OS-independent parts of std::io to alloc: traits, Cursor, Empty, Sink, buffering wrappers, etc. All OS-dependent functions and types will of course stay in std: stdio and pipes.
Unfortunately, some core items in std::io actually depend on the OS under the hood: Error (and unstable RawErrorType), IoSlice, IoSliceMut and copy. This is why this move has not been done earlier. The rest can easily be moved as it doesn't depend on anything else that is not already in alloc.
Here is the proposed plan for these:
ErrorandRawErrorType: move them toalloc, while keepingRawErrorTypeperma-unstable inalloc(for use instd). CreatingErrorfrom raw OS errors would only be possible instd, which is possible thanks to incoherent impls. When creating anErrorfrom a raw OS error,stdprovidesallocwith callbacks to decode them (could be replaced with externally implementable items).IoSliceandIoSliceMutare even easier, as they only depend on the OS for their exact layout:io_vecon Unix,WSABUFon Windows, etc. We can just have their definition inalloc, with a fallback for platform where the layout doesn't matter.copyhas specialization paths depending on the OS (eg usingsendfileorsplice). Inalloc,copywould only have the generic path, whilestdwould keep the specialized one. Such difference between standard crate in not new, it already exists with egpanic!.
Note that this proposal makes extra care to not expose anything OS-dependent to alloc users, only keeping that internal or perma-unstable for std; and to avoid linking to anything in alloc, as there are only structure definitions.
I understand that adding OS-dependent code to alloc is quite controversial, but I think that having alloc::io is worth the change.
A PR that successfully moves Error, IoSlice and IoSliceMut to alloc can be found at rust-lang/rust#152918.
Alternatives
- Do nothing, ie keep
std::ioinstd. - Create new traits with a custom error type, like [ACP] IO traits in
core::io#293.
This proposal has the disadvantage of creating new trait, and therefore is harder to make compatible with the current ecosystem. - https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/Lang.20.2B.20Libs-API.20interest.3A.20impl.20subtrait.20via.20supertrait/near/560051418
This proposition adds language features to try to create new traits while keeping compatibility. This is much more complex and has no concrete path to stabilization.
Possible future work
-
Try to move some parts of
iotocoreinstead ofalloc.
This will probably be quite difficult asReaddirectly depends onVec. -
Compatibility with
#[cfg(no_global_oom_handling)]
This should be possible for most ofalloc::ioto handle OOM errors throughio::Error, though some PR in this direction has already been rejected (Handle OOM when writing toVecrust#148024).
Links and related work
Tracking issue: rust-lang/rust#48331
Prior try to move Error to core (not alloc): rust-lang/rust#116685
Current PR for OS-specific parts: rust-lang/rust#152918
https://internals.rust-lang.org/t/a-plan-to-move-most-of-std-io-to-alloc/23678
Many #![no_std] crates reimplementing std::io:
embedded-iocore2and its forksciborium-io, created byciboriumto supportno_std.
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.
Second, if there's a concrete solution:
- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.