-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amend RFC 517: Revisions to reader/writer, core::io and std::io #576
Conversation
type NonatomicResult<S, T, Err> = Result<S, PartialResult<T, Err>>; | ||
|
||
// Ergonomically throw out the partial result | ||
impl<T, Err> FromError<PartialResult<T, Err> for Err { ... } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing a >
```rust | ||
trait Writer { | ||
type Err; | ||
fn write(&mut self, buf: &[u8]) -> Result<uint, Err>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To help avoid tons of subtle breakage when this change is made, can we rename the current write
method to write_all
at some point before the complete overhaul happens? It'll force everyone to switch their code to the thing that will be semantically the same before this lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds like a good idea!
I believe I should repeat my question about EINTR here. Is there any agreement on how EINTR is handled by The problem is that if EINTR is returned as error by those methods, it means that for example running a However if EINTR is consumed by internal loop of |
`ReaderExt`). These iterators will be changed to yield | ||
`NonatomicResult` values. | ||
|
||
The `BufferedReader`, `BufferedWriter` and `BufferedStream` types stay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The names for the trait and the type still conflict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, I still like
- Reader -> Read
- Writer -> Write
- Buffer -> ReadBuffer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
2015年1月13日 下午1:03于 "Steven Fackler"
FWIW, I still like
Reader -> Read
Writer -> Write
Buffer -> ReadBuffer—
Reply to this email directly or view it on GitHub.
@tailhook I think APIs returning |
`Writer` (and various adapters built on top of them) from moving to | ||
`libcore` -- `IoError` currently requires the `String` type. | ||
|
||
With associated types, there is essentially no downside in making |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. It seems like if we move this into core
, it couldn't be bounded by std::error::Error
, right? This could be a problem when interoperating with other pieces of infrastructure that are explicitly bound by Error
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any additional bounds on the error type you want to apply can be done when you're bounding over a Reader
or Writer
.
I'd first recommend taking a look at this article about EINTR (just did so myself for a refresher!), it's got some great information about EINTR and what it can be used for. The gist of the message is that EINTR cannot be used to reliably catch a "please interrupt" signal to the program in the case of syscalls like Due to our commitment to cross platform compatibility as well as the objects being somewhat high-level primitives, I think we will continue to swallow As @nodakai mentions, however, it may be useful to handle this case (such as if you're manually using For example, |
@nodakai, the issue with "D" state is both rare enough and impossible to do something about so we should not care. In many other cases Ctrl+C works. Not being able to use is very very annoying. There are precedents of bad SIGINT handling in history, for example SVN versions 1.1-1.4 (IIRC) were not handling the signal fast (could linger for minutes) and that was deemed as a bug. And you know, you usually can press Ctrl+/ or just kill process externally, but that does not execute destructors. And I don't wan't another bag of utilities that do same. @alexcrichton, while I can live with Sure, complex programs like network servers which will use low level level API, unblocking calls, asynchronous loop like "mio", and will use signalfd (or polyfill) anyway, so will not suffer this problem. But then what the high-level cross-platform interface is designed for? Is it for command-line tools that either hang or die without a cleanup? Is this only because they can't do anything better on Windows? Then I guess it's better to turn EINTR to error or even panic on it, in which case if the error is unhandled, at least it will execute all the destructors. I think we may return some |
As mentioned in the article that I linked to, using EINTR to handle an interrupt for your program in some form is racy (and generally not correct) if all you're using is the I definitely agree that we'll want a nice way to interrupt small programs performing various operations, but I don't think that EINTR is the right way to do so. Doing this, however, would require deeper modifications to the I/O interfaces to enable something along the lines of:
These are both somewhat involved, which is definitely where some high-level abstractions would help out! These may not exist in the standard library immediately, but I'm sure they'll start popping up in Cargo soon though. To reiterate, handling an interruption via EINTR in
A crucial part of the stabilization of |
@alexcrichton, I agree with most of what you say, but:
Sounds like "never use abstractions in standard library". So why they are there in the first place? Well, in fact the more I think about it the more I like idea of |
I feel like this probably belongs here; I feel it would be nice to have a "SearchableReader" trait which is like a Reader, but you can change the position inside of it. |
|
||
```rust | ||
trait Reader { | ||
type Err; // new associated error type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really worth saving 2 keystrokes here? Please just name it Error
, we already have far too many unnecessary abbreviations in the Rust std library and newcomers are rightly complaining about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt it. Unlike a |
This commit is an implementation of [RFC 576][rfc] which focuses on some of the more core aspects of `std::io`. It re-introduces a new `std::io` module with the base set of traits, helpers, and adaptors. The module is not currently ready for prime time as it is not integrated into the rest of the system, but some proof-of-concept implementations and methods are now available. [rfc]: rust-lang/rfcs#576 This module will grow quickly over the next few weeks as more I/O RFCs land and as the `old_io` module is slowly deprecated and phased out. At this time it is not recommended for use, but it is helpful to land in-tree to start developing more implementations.
Some concerns from @mahkoh on the implementation: rust-lang/rust#21835 (comment) The
Just a point to clarify. rust-lang/rust#21835 (comment) Should rust-lang/rust#21835 (comment) A suggestion that rust-lang/rust#21835 (comment) A suggestion to use @mahkoh if I misrepresented anything, please let me know! I'll try to copy over future worries to this RFC as well. |
It seems the issues with the associated error types mentioned by @alexcrichton are quite easily solved and don't load to any major ergonomic issues.
See this branch: https://github.com/Tobba/rust/tree/core-io which ports librbml to an (incomplete) implementation of a proposal for the I/O design. |
One of the key points I personally found was that porting librustc to use librbml was incredibly painful, I never actually got it to compile! The rbml implementation does not necessarily leverage I would encourage you to write some tests for the various primitives as well because it ended up leading to tests looking like this versus looking like this |
I would demonstrate these things myself, but I cannot build the standard library ATM. |
Some replies to @mahkoh's concerns:
I think we should have
I think @mahkoh is raising a good point here, and
The proposal in the comment, in particular, says that
This connects to broader API guidelines, of course, but in general in Rust APIs we use types to convey semantic content/limitations when possible. |
Updates from implementation and feedback:
re: EINTR handling I think at a minimum you should LOUDLY document any function that can Also, I think it would be more conservative to make read/write retry EINTR On Fri, Jan 30, 2015 at 1:25 PM, Aaron Turon [email protected]
|
At this time it looks like there's broad enough support for this amendment that I'm going to merge it. There are still some concerns about using a concrete There are also some lingering concerns about There have also been a number of proposals for backwards-compatible extensions. Due to this compatibility this RFC is going to go ahead and land ahead of them and future RFCs can be used to add new traits and/or methods where the design can be hashed out. I'd like to again emphasize that none of this functionality will land initially as I'd like to thank everyone again who participated in this thread (and #517!), all the comments have been quite helpful and this is all definitely moving in a great direction. Thank you! |
This commit is an implementation of [RFC 576][rfc] which adds back the `std::io` module to the standard library. No functionality in `std::old_io` has been deprecated just yet, and the new `std::io` module is behind the same `io` feature gate. [rfc]: rust-lang/rfcs#576 A good bit of functionality was copied over from `std::old_io`, but many tweaks were required for the new method signatures. Behavior such as precisely when buffered objects call to the underlying object may have been tweaked slightly in the transition. All implementations were audited to use composition wherever possible. For example the custom `pos` and `cap` cursors in `BufReader` were removed in favor of just using `Cursor<Vec<u8>>`. A few liberties were taken during this implementation which were not explicitly spelled out in the RFC: * The old `LineBufferedWriter` is now named `LineWriter` * The internal representation of `Error` now favors OS error codes (a 0-allocation path) and contains a `Box` for extra semantic data. * The io prelude currently reexports `Seek` as `NewSeek` to prevent conflicts with the real prelude reexport of `old_io::Seek` * The `chars` method was moved from `BufReadExt` to `ReadExt`. * The `chars` iterator returns a custom error with a variant that explains that the data was not valid UTF-8.
This commit is an implementation of [RFC 576][rfc] which adds back the `std::io` module to the standard library. No functionality in `std::old_io` has been deprecated just yet, and the new `std::io` module is behind the same `io` feature gate. [rfc]: rust-lang/rfcs#576 A good bit of functionality was copied over from `std::old_io`, but many tweaks were required for the new method signatures. Behavior such as precisely when buffered objects call to the underlying object may have been tweaked slightly in the transition. All implementations were audited to use composition wherever possible. For example the custom `pos` and `cap` cursors in `BufReader` were removed in favor of just using `Cursor<Vec<u8>>`. A few liberties were taken during this implementation which were not explicitly spelled out in the RFC: * The old `LineBufferedWriter` is now named `LineWriter` * The internal representation of `Error` now favors OS error codes (a 0-allocation path) and contains a `Box` for extra semantic data. * The io prelude currently reexports `Seek` as `NewSeek` to prevent conflicts with the real prelude reexport of `old_io::Seek` * The `chars` method was moved from `BufReadExt` to `ReadExt`. * The `chars` iterator returns a custom error with a variant that explains that the data was not valid UTF-8.
The IO reform RFC is being split into several semi-independent pieces, posted as PRs like this one.
This RFC amendment adds the sections on
Reader
/Writer
revisions, as well ascore::io
andstd::io
(which are closely related).Rendered