-
Notifications
You must be signed in to change notification settings - Fork 533
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
0.5: Converting the API to return Results (part 1) #1410
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## 0.5.x #1410 +/- ##
==========================================
- Coverage 94.16% 94.14% -0.03%
==========================================
Files 34 35 +1
Lines 16824 16849 +25
==========================================
+ Hits 15842 15862 +20
- Misses 982 987 +5 ☔ View full report in Codecov by Sentry. |
c97458b
to
dd8e32e
Compare
Yes! Would commits like this be helpful? It is based on this pull request and prepares to include It also highlights some difficulties with too simplistic naming. "INVALID" is very dependent on the context. We could either use "INVALID" for invalid fields, parameters or dates or split them into variants. I'm fine with either, the core contributors will surely have a better feedback how the naming schemes will play out best. Iteratively changing the error names would also be an option and facilitates getting a foot in the door. The downside would be a bit more code churn. |
Great! Thank you. My plan for the parsing errors was a bit more involved than mapping the existing Are you interested in starting with I'll reply to the rest of your comment later today. |
I did put quite some thought the error variants 😄.
I don't want to make the errors much more specific, like splitting As another example I did propose a split between
I am all for iterating. Our core types and operations should be covered, and parsing and formatting are mostly covered. The OS integration part is something to iterate on. |
// parsing of a `TZ` environment variable. | ||
#[non_exhaustive] | ||
#[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||
pub enum 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.
Instead of adding this at the beginning, I would prefer to add variants one-by-one as they are needed by the changes you make.
Also, please order the variants alphabetically.
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.
Okay, that can work for me.
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.
One more nit, I think it would now make sense to just inline this commit into the next one, so we don't introduce unused code here.
src/naive/date.rs
Outdated
@@ -768,7 +768,7 @@ impl NaiveDate { | |||
#[inline] | |||
#[must_use] | |||
pub const fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> { | |||
let time = try_opt!(NaiveTime::from_hms(hour, min, sec)); | |||
let time = try_opt!(ok!(NaiveTime::from_hms(hour, min, sec))); |
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.
Given that we have four instances of try_opt!(ok!())
here, I would suggest making a macro specifically for that instead of/in addition to the other ones you've added 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.
While working on this I expect we are going to frequently hit the case where one method is already converted to a Result
while the existing callers are still returning an Option
. Having a single macro to convert it with minimal changes to the surrounding code was my goal 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'm not sure how this is at odds with my suggestion? Maybe just being dense.
Thank you for looking at this! Sorry for being difficult in #1417. |
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'm okay with these code changes, but... I'm not very convinced the distinction between InvalidArgument
and DoesNotExist
is meaningful? If "the nanosecond part to represent a leap second is not on a minute boundary", isn't that very similar in practice to trying to Feb 29 in a non-leap year? Do we have other intended use cases for DoesNotExist
?
// parsing of a `TZ` environment variable. | ||
#[non_exhaustive] | ||
#[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||
pub enum 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.
One more nit, I think it would now make sense to just inline this commit into the next one, so we don't introduce unused code here.
src/naive/date.rs
Outdated
@@ -768,7 +768,7 @@ impl NaiveDate { | |||
#[inline] | |||
#[must_use] | |||
pub const fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> { | |||
let time = try_opt!(NaiveTime::from_hms(hour, min, sec)); | |||
let time = try_opt!(ok!(NaiveTime::from_hms(hour, min, sec))); |
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'm not sure how this is at odds with my suggestion? Maybe just being dense.
My idea for
If a method can only fail because of For me it feels like a very different kind of error that arises in other situations than |
How would you practically handle it differently in calling code? If I understand correctly you want to yield |
4556d3e
to
ebf70c9
Compare
At least as a property of the documentation I think keeping them seperate is going to be a great help. My biggest issue before working on chrono was figuring out all the potential failure causes. Now I have already made that part of our documentation in almost all cases. Encoding the causes (at least at a fundamental level) as part of the Then there is the argument that the cause is somewhat different in nature.
Admittedly for code calling only constructor methods such as Shall we re-evaluate once the work is a bit further along than the first 7 methods? Combining errors is much easier than splitting them up later. |
Fair! |
This is the first small step to convert the API to return
Result
's.I have been looking forward to working on this for a long time. Now that most panic cases are fixed, our const work is done, and the 0.5 branch has had some basic clean-ups it seems like a good time to start.
Error
enumThe first commit introduces a basic
Error
enum. We can grow it as needed and bikeshed the variant names.#1049 has a (slightly outdated) summary our API and the error cases that can arise. I diverged a bit from the latest design in #1049 (comment):
Error::InvalidCharacter
andError::InvalidValue
are new. They are for our parsing code, so not entirely relevant yet to this PR. I'll add a comment to Converting the API to return Results #1049 describing them.UnsupportedSpecifier
is new. My idea was to useError::ParsingError
for parsing errors in both the format string and input string. But it is better to keep them separated.First methods:
NaiveTime::from_hms*
andNaiveDate::and_hms*
These methods are reasonably stand-alone and give a taste of the direction.
I added an
ok
macro to help with converting the API piece-by-piece. We can't useOption::ok
because it is not available in const functions.Next work
Duration
/TimeDelta
can probably be done independent of the rest of the API.FixedOffset
can probably be done independent of the rest of the API.NaiveDate
. Removing theDateImpl
andOf
abstractions in Refactorinternals
module #1212 will help a lot for this. So I'll wait until that makes it to the 0.4 branch and then to 0.5.NaiveDateTime
becomes easy afterNaiveDate
is done.Datelike
trait depends onNaiveDate
.DateTime
depends on changes toLocalResult
and theTimeZone
trait first.local::tz_info
can probably do with a refactor first. Or we should just convert its error types at the boundary.The rest will just be a discovery of which changes don't result in massive commits.
@Zomtir Still interested in biting off a piece of the work?