Skip to content
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

Add conversions from io:ErrorKind to io::Error #37037

Merged
merged 1 commit into from
Nov 4, 2016

Conversation

Mark-Simulacrum
Copy link
Member

Filing to help with discussion around the possibility of doing this.

Current changes are clearly backwards incompatible, but I think adding a new function (with a bikeshed on naming) like Error::new_str should be possible (or some other way of specializing the string error message case) to fix #36658.

@rust-highfive
Copy link
Collaborator

r? @sfackler

(rust_highfive has picked a reviewer for you, use r? to override)

@Mark-Simulacrum Mark-Simulacrum force-pushed the stack-error branch 2 times, most recently from 6b252bc to 43decfc Compare October 9, 2016 14:36
@sfackler sfackler added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Oct 9, 2016
@sfackler
Copy link
Member

sfackler commented Oct 9, 2016

io::Error's layout was designed to mimimize its size since it is so frequently passed around. I would be somewhat worried about blowing it up from 16 bytes to 40. If the message is cut out we should be okay size wise though.

@Mark-Simulacrum
Copy link
Member Author

Cutting the message out would make us lose information, though, which is why it seems best not to do that; though I'm not sure how often the messages carry meaningful information with them not already included in the ErrorKind.

@sfackler
Copy link
Member

I think I'd personally want to hear a very compelling story around why it's crucial to have custom messages and not allocate at the same time before blowing up io::Error's size. The use case described in the related issue wants to avoid allocation because the errors are being generated very frequently, in which case a user isn't going to be looking at the message almost by definition.

@Mark-Simulacrum
Copy link
Member Author

I'll push code sometime soon removing the Cow from the non-allocating repr variant; I agree that it's unlikely an accompanying message would be useful for the case this is intended to be used for.


On another note, can someone explain/help me out to see why Travis is failing and how to fix it? I didn't change anything inside Vec, but I see "std/vec/struct.Vec.html:2447: id is not unique: src-3909" in the Travis log during stage2 linkcheck before it fails.

@sfackler
Copy link
Member

Dunno what's going on with the travis errors. Seems like it's probably a false alarm?

@Mark-Simulacrum
Copy link
Member Author

I've pushed (force) a couple times already, and it's repeated itself a couple times (same error), so I feel like it might not be.... though I agree it feels spurious.

@bluss
Copy link
Member

bluss commented Oct 10, 2016

No reason to have a String or Cow in a non-heap variant. Needs a different solution, for example there is room for an application-specific error identifier (number) in addition to ErrorKind, but it's not going to be easy to use.

@alexcrichton
Copy link
Member

I agree with @sfackler that the representation here was chosen pretty precisely to ensure an efficient runtime representation, and we'd likely want some strong numbers to change it much.

In the current iteration, though, I'm not sure I understand what the benefit is over just from_raw_os_error perhaps? That way it seems like you at least get a more descriptive message?

@Mark-Simulacrum
Copy link
Member Author

from_raw_os_error doesn't allow you to specify an error kind directly, which I think is useful.

Adding a u64 or another integer/number type to the new variant will also work (no increase in size); but I'm not sure how useful that is, since it will be library specific and difficult to differentiate between (library A and B could use the same error kind and attached integer for different meanings, which would get confusing).

@alexcrichton
Copy link
Member

@rfcbot fcp close

With the particulars around the representation chosen here I personally feel that just being able to construct from a kind isn't quite strong enough motivation to add this here. I could perhaps be persuaded with numbers though!

@rfcbot
Copy link

rfcbot commented Oct 24, 2016

Team member @alexcrichton has proposed to close this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@Mark-Simulacrum
Copy link
Member Author

@alexcrichton The issue (#36658) which spurred this PR suggests that heap-allocating errors is significant. Can you document your thoughts on how crates/libstd should be creating stack-allocated errors for the common case (e.g. ErrorKind::WouldBlock)?

Is the intent that crates would use the Error::from_raw_os_error(i32) method? I find that a poor suggestion, since it implies being platform-specific, which AFAIK is something Rust tries to avoid.

@aturon
Copy link
Member

aturon commented Oct 25, 2016

I was going to suggest that we could provide a conversion from ErrorKind to raw OS errors, but unfortunately, not every OS can represent every error kind.

However, perhaps we could offer a conversion from ErrorKind to Error, which goes via Os when possible, and falls back to Custom otherwise? I think that would achieve basically the aims of this PR, without any representation changes. The main downside is the fact that it'd sometimes hide an allocation (but only for more obscure errors). If that turns out to be a problem in practice, though, we could always introduce an additional variant later.

@alexcrichton
Copy link
Member

@Mark-Simulacrum Unfortunately we still don't have numbers one way or another (beyond microbenchmarks), so the perf wins are still somewhat heresay. Crates can always create a non-allocating version like the standard library does, which is to use from_raw_os_error, yeah.

@aturon that's essentially what this PR does, adding Error::new_kind(kind: ErrorKind). I've always felt like we never really expanded ErrorKind as much as we could, so it's not quite ready for a prominent placement like that. Falling back to what the standard library does, using OS errors, seems reasonable in the interim.

@aturon
Copy link
Member

aturon commented Oct 25, 2016

@alexcrichton Right, but I'm saying we could do it without adding another variant. In your comment you mentioned "the particulars of the representation" so I was thinking you were concerned about the representation change.

I also disagree about the prominence of ErrorKind. It's how you figure out anything about errors in a platform-generic way today, and I don't see adding a constructor as any more of a commitment than our current APIs.

@alexcrichton
Copy link
Member

Oh we can add new variants so long as they don't inflate the size of the payload. The current PR would suffice for that. I erroneously remembered this as having a new Simple(&'static str) which would inflate the size.

@aturon
Copy link
Member

aturon commented Oct 25, 2016

@alexcrichton OK -- so can you elaborate a bit more on your concern here? Having a platform-agnostic, lightweight way to go from an ErrorKind to an Error seems like good functionality to me.

@sfackler
Copy link
Member

I'm moderately in favor of adding this as well. The extra variant shouldn't cause any size blowup and I can see the allocation cost mattering in certain rare-ish situations.

@alexcrichton
Copy link
Member

I would find it a little odd that we can construct an error with so little information. An error created with only an ErrorKind is virtually useless to ever present to anyone, and only really serves a purpose of some downstream match statement looking at the kind. I suppose if the errors are basically guaranteed to be inspected in that fashion that's ok, so perhaps this is an ok addition?

@Mark-Simulacrum
Copy link
Member Author

I believe the point is that some IO Errors (and ErrorKinds) are usually not intended for presentation to the user; e.g. WouldBlock seems to be mainly a program-internal error message, not something the user would care about.

I can add to the documentation comment (did I write one?) to include that this is intended for library/application-internal error construction that will not be exposed to the end user.

@alexcrichton
Copy link
Member

Ok, given that information, let's go the other way instead:

@rfc fcp cancel

@alexcrichton
Copy link
Member

@rfcbot fcp cancel

@rfcbot
Copy link

rfcbot commented Oct 31, 2016

@alexcrichton proposal cancelled.

@alexcrichton
Copy link
Member

@rfcbot fcp merge

@Mark-Simulacrum
Copy link
Member Author

Just so it's clear, this shouldn't be merged yet--documentation needs to be added. I don't really want to type it out prior to a decision wrt to merging, though.

@sfackler
Copy link
Member

Can we land this thing? This PR has been open for 23 days. It really doesn't seem necessary to wait around for another week.

@rfcbot
Copy link

rfcbot commented Oct 31, 2016

Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@Mark-Simulacrum
Copy link
Member Author

Mark-Simulacrum commented Oct 31, 2016

Two things that would need to be discussed:

  • A name (with_kind?)
  • How should we document the intent for this to be used only for library-internal errors?

@alexcrichton
Copy link
Member

@sfackler remember that "FCP" for PRs is insta-merge, no need to wait for a week (just need to wait for eyes).

I personally feel this should be called new_kind and then we'd also want to update the docs before landing, yes. We'd just call out explicitly how it's intended for internal errors that are inspected later.

@sfackler
Copy link
Member

At least judging from every other T-libs PR, it'll take at least a week to get everyone to check their boxes.

new_kind seems fine, or from_kind.

@alexcrichton
Copy link
Member

I'd actually also be fine with just:

impl From<ErrorKind> for Error {
    // ...
}

@aturon
Copy link
Member

aturon commented Oct 31, 2016

👍 for From<ErrorKind>.

@brson
Copy link
Contributor

brson commented Oct 31, 2016

From conversion makes sense to me.

@brson brson added the relnotes Marks issues that should be documented in the release notes of the next release. label Oct 31, 2016
@brson brson changed the title Add a new non-heap allocated variant to io::Error's representation. Add conversions from io:ErrorKind to io::Error Oct 31, 2016
@sfackler
Copy link
Member

SGTM

@Mark-Simulacrum Mark-Simulacrum force-pushed the stack-error branch 2 times, most recently from e8ed76e to 35b5a1a Compare November 2, 2016 01:32

/// Intended for use for errors not exposed to the user, where allocating onto
/// the heap (for normal construction via Error::new) is too costly.
#[stable(feature = "io_error_from_errorkind", since = "1.13.0")]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the right tag here.

@Mark-Simulacrum
Copy link
Member Author

Implemented the From<ErrorKind> for Error as suggested. Ready for another review.

I'm not sure if the documentation comment is sufficiently emphatic about not exposing this "raw" container to users, please let me know if you have better text for it.

Implement From<ErrorKind> for io::Error, intended for use with errors
that should never be exposed to the user.
@alexcrichton
Copy link
Member

Looks good to me!

@rfcbot
Copy link

rfcbot commented Nov 3, 2016

🔔 This is now entering its final comment period, as per the review above. 🔔

psst @alexcrichton, I wasn't able to add the final-comment-period label, please do so.

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Nov 3, 2016

📌 Commit 99234bb has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Nov 4, 2016

⌛ Testing commit 99234bb with merge d2bc30b...

bors added a commit that referenced this pull request Nov 4, 2016
Add conversions from `io:ErrorKind` to `io::Error`

Filing to help with discussion around the possibility of doing this.

Current changes are clearly backwards incompatible, but I think adding a new function (with a bikeshed on naming) like `Error::new_str` should be possible (or some other way of specializing the string error message case) to fix #36658.
@bors bors merged commit 99234bb into rust-lang:master Nov 4, 2016
@carllerche
Copy link
Member

Thanks for making this happen @Mark-Simulacrum

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

io::Read / io::Write fns can cause a lot of allocations via io::Error::new
10 participants