-
Notifications
You must be signed in to change notification settings - Fork 588
Description
Many constructors in chrono
has the behavior to panic on invalid inputs. This issue proposes to systematically change this behavior to instead make use of fallible constructors which in effect means the removal of the *_opt
family of functions.
I'll be trying to make an argument for why below, at the end are the concrete changes I'm proposing.
Why should we do this?
The use of chrono
has been the culprit of many unwanted panics in code that I've personally written in my career as a Rust programmer. The reason why this happens is sloppiness from my part. I use a method without realizing that it panics even though it says so in the documentation. But after consideration I've come to believe that the design of these methods could be improved.
The standard I abide by when it comes to panicking is broadly that correct Rust programs should not panic. So what I'll try and determine next is if uses of these constructors contributes to writing correct Rust programs that do or do not panic.
There are a few tests I'll be applying here each time one of these methods are used:
- Does the caller check the necessary preconditions before calling the function?
- Does the caller control the input to the function so that it's runtime invariant?
- Is the function call in a context where it's OK to panic. Such as a test case or a short lived CLI program.
Preconditions
If we look at the doc for most of these functions they contain wording such as TimeZone::ymd
:
Panics on the out-of-range date, invalid month and/or day.
This is a difficult precondition to check. An out-of-range date isn't a mechanical test such as "is this value smaller than 1000". It requires a deep understanding of the gregorian calendar system which chrono
itself is responsible for providing. It's implausible that uses ensure that its input passes the required condition due to complexity. So the first test probably fails systematically across many projects.
Runtime invariant inputs or tests
It's easy to find many uses of these functions where the input is runtime variant and not tests. I've found that many of these relate to ad-hoc use in combination with serde
, which is a strong indication that its arguments truly are runtime variant. A bit of taxonomy lead me to believe that there might be a case of systematic misuse.
What to do?
I believe many of the examples one can find of chrono
production use fails the tests I proposed. The way to correct these uses would be through the *_opt
family of methods. But since the non-opt methods seems to be considered the default and probably leads to systematic problems when used I think it's worth considering changing them.
What I'd suggest and would like to discuss is:
- Rewrite all panicking functions that do not have an easy precondition to test to be fallible instead.
- Consider rewriting other functions which panic if there is a high risk of misuse where the caller should actually be using the
*_opt
sibling function but for one reason or another doesn't. - For all the rewritten functions: deprecate or remove their
*_opt
sibling function.
Thank you!