-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
proposal: cmd/vet: time.Time should not compared #45961
Comments
related #22978 |
Comparing times is an acceptable usage as described in the document, although extra care is needed: "Note that the Go == operator compares not just the time instant but also the Location and the monotonic clock reading. See the documentation for the Time type for a discussion of equality testing for Time values." Issues (#45958 #45960) are more related to the marshaling and unmarshaling of the time object. Since Specific fields will be ignored during marshaling/unmarshaling, the "==" operator will already return false. "the serialized forms generated by t.GobEncode, t.MarshalBinary, t.MarshalJSON, and t.MarshalText omit the monotonic clock reading, and t.Format provides no format for it. Similarly, the constructors time.Date, time.Parse, time.ParseInLocation, and time.Unix, as well as the unmarshalers t.GobDecode, t.UnmarshalBinary. t.UnmarshalJSON, and t.UnmarshalText always create times with no monotonic clock reading". So the problem is to compare two times after marshaling/unmarshaling rather than comparing two times generally, and the following patterns are not necessarily bugs? if time.Time{...} == time.Time{...} {} In addition, if we want to capture these general patterns, a StaticCheck checker seems more appropriate. |
the phrase "extra care is needed" scares me; I agree with your assertion, there exist cases where informed users can safely use if we feel this check is too false positive prone, I think moving it to StaticCheck is reasonable, but I would always prefer first party integrations, so I started here. |
Here is an excerpt from the documentation on time.Time on comparisons:
This sounds like there exist valid usages (an real world example would be nice), but these are tricky to get right and [at least] moderately error prone.
This comment from #22978 is I think basically still the issue for vet:
Evidence to answer the false positive question would be great. If this is low enough, vet could consider it. vet probably is not the right home at a 10% false positive rate. We have evidence of bugs that could be caught but no great sense of how many people would be impacted if we turned this on. /cc @richardartoul did a check for this ever make it into gometalinter ? |
I see two use cases:
There is an argument about hyrum's law, but since this is just a vet, I am convinced it is not too dangerous. this reads like how we disallow
example does not have any references to
is not the gometalinter basically dead? and golangci-lint does not define its own lints. |
Basically it's fine to compare I have seen code that constructs |
Given the possible confusion people may have, now I am inclined to have a checker for this. Typically, the The remaining problem is whether the incoming StaticCheck suggestion is sufficient, or we need to go deeper, e.g. see whether the Time object comes from In addition, what I am thinking now is whether this can be generalized to other data types than just Time. Such a checker will analyze whether a "Equal" function is defined on a data type, if so then it will discourage (1) using |
The docs make clear that it is perfectly fine to use time.Time with == and in map keys provided you do it correctly. |
This proposal has been added to the active column of the proposals project |
After @ianlancetaylor 's comment about time.Date, I think this would require showing a flow from a known "bad for equality" source like time.Now() into an == without modification to the Time like UTC(). This is a fairly considerable step up in difficulty compared to warning on every == on type time.Time and will warn on a lot less stuff. |
Without knowing more about the relationship of == and Equal on that type, this sounds like it will have too many false positives. |
I think we have established that there are cases where experienced developers can use why did we even make a single time symbol that embeds wall clock, monotonic, and location based time information, if not to create one one a simple, easy to use interface? |
There's just no way for a tool to know whether I wrote the code correctly or not. This is not a good topic for vet. Vet needs to be sure. |
Based on the discussion above, this proposal seems like a likely decline. |
if we are not pursuing this avenue, what is the suggested resolution to the meta issue "time.Time is hard to use"? I am happy to start an out of band discussion or look into alternatives, but it suggesting people rtfm does not appear to be working. |
I'm not sure, but see also #20757 (which is basically “ |
No change in consensus, so declined. |
No change in consensus, so declined. |
background
Time is hard and
time.Time
is really great in most all cases, but between the two issues (#45958 #45960) I came across recently, it seems like anything that does a runtime equality check is probably a bug. Please let me know if there are cases where comparing time is good, safe, and necessary.summary
As such, it seems reasonable to add a vet check to disallow using
time.Time
like so:alternatives
I support enforcing this via the complier, but I get the impression that is a non starter:
We could also add a new symbol that is intentionally comparable, say
time.Comparable
, but it would be somewhat confusing when to use which one, and that would probably involve ago vet
rule too.The text was updated successfully, but these errors were encountered: