-
Notifications
You must be signed in to change notification settings - Fork 2
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
Common error details, as @newpavlov's design #30
Conversation
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.
Looks good.
Have you measured the type is 32 bytes?
Edit: it is.
rand_core/src/lib.rs
Outdated
} | ||
write!(f, "RNG {} (details: {})", | ||
self.kind.description(), | ||
self.details().unwrap_or("NA")) |
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.
We maybe should not print the details here, see rust-lang-deprecated/error-chain#154 (comment)
rand_core/src/lib.rs
Outdated
self.cause.as_ref().map(|e| &**e) | ||
match self.details { | ||
ErrorDetails::Error(ref e) => Some(&**e), | ||
// unforunately we cannot report &str cause here |
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 think we can if ErrorDetails
where to implement std::error::Error
. Or by implementing std::error::Error
for ErrorDetails::Str(...)
rand_core/src/lib.rs
Outdated
/// Create a new instance, with a static string describing the details. | ||
/// | ||
/// This may be used in both `std` and `no_std` enviroments. | ||
pub fn new_str(kind: ErrorKind, details: &'static str) -> Self { |
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 name could be a little bit confusing. Maybe a more verbose new_with_cause_str
?
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.
Why the long name?
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 agree with new_str
being a bit confusing, but I personally can't come up with the better alternative, so I guess we can leave it up to docs.
rand_core/src/lib.rs
Outdated
Error { | ||
kind: kind, | ||
cause: cause, | ||
pub fn new_err<E>(kind: ErrorKind, cause: E) -> Self |
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.
Does it make sense to have a function that takes both a kind and a string, and use one of them depending on whether the std
feature is enabled? Now implementations of Rng
need a std
feature flag to give the right type of cause.
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 don't get what you mean? This is more generic than new_str
and can still accept a string but is only available with the std
library (we could probably depend on alloc
instead, but that's another matter; we need Box
).
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.
See this comment.
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 Into
where clause it neat, wouldn't have thought about that myself. Although maybe it is common, and I am just missing something :-).
I was thinking about cases like this, where a Rng
implementation needs to use different functions to construct an error depending on whether the std
feature is available.
Then a helper function is maybe useful:
The `Into` where clause it neat, wouldn't have thought about that myself. Although maybe it is common, and I am just missing something :-).
``` rust
#[cfg(feature="std")]
pub fn new_with_cause(kind: ErrorKind, cause: E, details: &'static str) -> Self {
new_str(kind, details)
}
#[cfg(not(feature="std"))]
pub fn new_with_cause(kind: ErrorKind, cause: E, details: &'static str) -> Self {
new_err(kind, cause)
}
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.
In no_std
environment you simply can't have implementation of Error
trait, as it's defined only in the std
. So either way crate authors will have to write cfg
s to handle switching.
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.
Or authors supporting no_std
can simply use new_str
with a string description everywhere. There's no advantage to using new_err
if the details are just a string.
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 updated my branch with JitterRng
to the new error handling pitdicker@b223c60.
The second commit shows what I mean pitdicker@f6b3531.
In theory an RNG implementation can support both std
and no_std
compatible error causes, and the choice is made in rand_core
.
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.
It was just an idea, but I don't think it helps in enough cases. Lets leave the two functions as is.
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.
Your new_with_cause
isn't even going to compile in no_std
mode since it depends on std::error::Error
.
I see what you mean, but I'm not convinced it's worth returning a chained Error
type in this case; there is no added information (but maybe your description()
strings should include all the details from the Display
impl).
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.
Oops. Ok, please forget I said anything :-)
rand_core/src/lib.rs
Outdated
/// | ||
/// In the case of a chained error, the actual error may be obtained via | ||
/// `std::error::Error::cause`. | ||
pub fn details(&self) -> Option<&str> { |
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.
Maybe "will be obtained"? Also not description
, but cause
.
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.
Um, actually I think my description is correct, but I'll try to make it clearer.
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 meant in reverse. :) In the code description()
method is used, but in the docstring you write about cause
.
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.
This is the details()
function. Anyway, the terms are a bit confused, although description
should be distinct from details
/cause
rand_core/src/lib.rs
Outdated
ErrorKind::Other => write!(f, "An unspecified RNG error occurred."), | ||
ErrorKind::__Nonexhaustive => unreachable!(), | ||
} | ||
write!(f, "RNG {}", self.kind.description()) |
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 think "RNG Error: {}" will be better.
rand_core/src/lib.rs
Outdated
impl ::std::error::Error for ErrorDetails { | ||
fn description(&self) -> &str { | ||
match *self { | ||
ErrorDetails::None => "NA", // case shouldn't be used |
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.
It's better to write unreachable!()
here if this case indeed can not be used anywhere.
Ok, I addressed some of your points. I don't see much point renaming the |
rand_core/src/lib.rs
Outdated
ErrorKind::Other => write!(f, "An unspecified RNG error occurred."), | ||
ErrorKind::__Nonexhaustive => unreachable!(), | ||
} | ||
write!(f, "RNG error: {}", self.kind.description()) |
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.
According to the book description
is supposed to be a short description, and Display
a user-facing representation of the error (a proper sentence with capital letter, dot at the end, and a bit less condensed text).
I think this is okay, but like the previous version more.
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.
Does it? I skimmed through and saw an example similar to this, but in general the section is long and a little vague.
WARNING: this is a change in policy for ReseedingRng
Implement new design in #10.
Any comments @newpavlov or @pitdicker?
Error
should be 32 bytes in size (two enums padded for alignment + a fat pointer). It could potentially be reduced to 24 bytes by combining the two enums, but that would be ugly. Otherwise it could only be much smaller by omitting the details altogether. Hopefully the size doesn't make too much of a difference anyway; I don't know.Most of the "details" implementation is hidden and "kind" is still not exhaustively matchable.
Doc here