-
-
Notifications
You must be signed in to change notification settings - Fork 88
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 enum variant discriminant changed lint #912
Add enum variant discriminant changed lint #912
Conversation
Oh wow, we ... might have found a breaking change in clap? 😮 @dmatos2012 could you dig into the source code of clap at the version used in CI, and compare it to the previous clap release to see if the enum discriminant value indeed changed? If it didn't, that sounds like a false-positive we should investigate. If it did, we'll need to adjust what the CI test expects. |
@obi1kenobi Indeed, there are bunch of discriminant changes from
#clap-v3.1.18
Then clap-v3.2.0
So in this case Because
to
That being said, I guess should I adjust the TLDR: |
Nice, that looks legit. Do you think you can edit the clap CI test to expect both lints to trigger, or would you like some help/suggestions? |
@@ -0,0 +1,65 @@ | |||
SemverQuery( | |||
id: "enum_variant_discriminant_changed", | |||
human_readable_name: "Public enum's variant had its discriminant changed from its previous value", |
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 field is intended to be a name — it's printed in the headline of the CLI diagnostics we emit when breakage is found — so it should be quite short and it's okay if it doesn't have all the details.
Check out how these fields are used in the CLI ("what gets printed where") if you have a moment. I think that'll give you a better sense of what to put in the various fields going forward.
human_readable_name: "Public enum's variant had its discriminant changed from its previous value", | |
human_readable_name: "enum variant had its discriminant change value", |
Applied the change and changed the |
Just making sure you've seen this comment: #898 (comment) We should split this lint into two separate lints based on whether there's an ABI concern or just an API concern. This will let us offer specific feedback to the user that is stronger than "may break ABI." That's important because our users likely have a general expectation that Sorry I didn't catch this earlier, hope you don't mind making the tweaks! |
f427a45
to
b244d6b
Compare
b244d6b
to
5b9a24b
Compare
Yeah no problem, I dont mind making the tweaks. I have changed everything slightly, so it might as well be kinda like a new lint. I hope that I got all the details correctly, and if I am missing something, feedback is welcomed :) To reiterate, this is targeting |
.github/workflows/ci.yml
Outdated
EXPECTED="$(echo -e "--- failure auto_trait_impl_removed: auto trait no longer implemented ---\n--- failure enum_no_repr_variant_discriminant_changed: enum variant had its discriminant change value ---")" | ||
RESULT="$(cat output | grep failure)" |
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 if you can squeeze a sort
call after grep failure
here? I'm not sure if we guarantee (or want to guarantee) a particular order of lint outputs, and flaky tests are annoying so better avoid the risk whenever possible.
EXPECTED="$(echo -e "--- failure auto_trait_impl_removed: auto trait no longer implemented ---\n--- failure enum_no_repr_variant_discriminant_changed: enum variant had its discriminant change value ---")" | |
RESULT="$(cat output | grep failure)" | |
EXPECTED="$(echo -e "--- failure auto_trait_impl_removed: auto trait no longer implemented ---\n--- failure enum_no_repr_variant_discriminant_changed: enum variant had its discriminant change value ---")" | |
RESULT="$(cat output | grep failure | sort)" |
attribute @optional { | ||
content { | ||
base @filter(op: "!=", value: ["$repr"]) | ||
} | ||
} |
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 think we want @optional
here. Try adding an enum that has two non-repr attributes on it (e.g. #[non_exhaustive]
and #[allow(dead_code)]
) to see why.
There's a subtle difference in Trustfall between "if it has an attribute, it isn't repr" (AKA @optional
and @filter
like here) and "it doesn't have repr" (AKA @fold @transform(op: "count") ...
). The difference is around what happens on edges with cardinality greater than 1: in the former case we have a "left outer join" in relational terms, and in the latter (because of the @fold
aggregation), we don't.
|
||
variant { | ||
variant_name: name @output @tag | ||
discriminant @optional { |
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 @optional
here?
attribute @optional { | ||
content { | ||
base @filter(op: "!=", value: ["$repr"]) | ||
} | ||
} |
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 shouldn't matter if the enum now gained a repr, the API is still broken.
"repr": "repr", | ||
"true": true, | ||
}, | ||
error_message: "The public enum's variant had its discriminant changed from its previous value. This breaks implementors that relied on the discriminant value.", |
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.
Let's make sure to be very specific about what broke, and precise with terminology. Enums aren't traits so they don't have implementors.
error_message: "The public enum's variant had its discriminant changed from its previous value. This breaks implementors that relied on the discriminant value.", | |
error_message: "The enum's variant had its discriminant value change. This breaks downstream code that used its value via a numeric cast like `as isize`.", |
@@ -0,0 +1,78 @@ | |||
SemverQuery( | |||
id: "enum_no_repr_variant_discriminant_changed", |
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.
Naming is hard. This is not the best name, and not the worst. Nothing better comes to my mind, but if you have other suggestions, it would be good to consider them.
Thanks for working on this tricky lint! |
57851e5
to
9cda225
Compare
Hopefully this addresses all the changes requested :) But there is still a pending task, the renaming of the actual lint. Ill make the renames in the code once we come up with a good one, but for now i left since didnt want to rename everything too many times. Possible ones:
I dont know as you said, naming is hard and particularly this one. Specially since we would like to keep naming consistent with the other lints. |
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 lint name is fine, let's keep it. I spent a bunch of time thinking about alternatives, and couldn't come up with anything that didn't have worse downsides.
This PR is super close, it needs maybe one more round of polishing. I think there might be a bug in the query (which might be hidden by a feature by the underlying rustdoc plugin). There's also some imprecise language and use of terminology. Otherwise, good to go! 🚀
A quick meta suggestion outside this PR: consider going through past PRs, making a list of the changes I've suggested in reviews in the past, and using it as a checklist for things to self-review more closely before opening a new PR. With that list, you could catch pretty much everything I've commented on so far — and that's a great way to improve your skills and get more PRs done in less time.
span_: span @optional { | ||
filename @output | ||
begin_line @output | ||
} |
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.
Can we grab the span of the variant instead of the span of the enum? It's nicer to point to Example::Variant
instead of to enum Example
.
// This now implies that the enum is no longer `well-defined`, which means that a numeric | ||
// cast is no longer possible on the enum, should not be reported. |
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 now implies that the enum is no longer `well-defined`, which means that a numeric | |
// cast is no longer possible on the enum, should not be reported. | |
// This now implies that the discriminant is no longer `well-defined`, which means that a numeric | |
// cast is no longer possible on the enum. Should not be reported. |
Please try to use precise, clear language and good grammar as much as possible. Long sentences with lots of commas are hard to read.
Second = 2, | ||
} | ||
|
||
// Discriminant changed to be doc hidden and explicit. Being doc hidden is not relevant |
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.
Some more imprecise language:
// Discriminant changed to be doc hidden and explicit. Being doc hidden is not relevant | |
// Variant became doc(hidden) while variant became explicit. Being doc(hidden) is not relevant |
Unit = 5, | ||
} | ||
|
||
// Variant `Struct` acquires a field. By doing so, it makes the enum not `well-defined`, |
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.
// Variant `Struct` acquires a field. By doing so, it makes the enum not `well-defined`, | |
// Variant `Struct` acquires a field. By doing so, it makes the discriminant not `well-defined`, |
#[non_exhaustive] | ||
pub enum DiscriminantIsChangedButAlreadyNonExhaustive { | ||
First, | ||
#[non_exhaustive] |
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.
Could you add a test case where another variant is #[non_exhaustive]
, not the one that changes discriminant values?
I think there's a bug in the lint query related to it: the lint is checking for "is the variant with the changed discriminant marked #[non_exhaustive]
" when it should be checking for "does the enum have any #[non_exhaustive]
variants" — not quite the same thing.
Thanks for the detailed feedback, is greatly appreciated. I did the following:
Regarding clarity or precision in language: Every new PR either on Thanks again for the detailed feedback and HOPE that this time is good. This has been a very tricky lint for me, specially if compared with my first two lints :) |
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.
Go team! Excellent work, I'm thrilled to see you keep improving with every new PR 🚀
Adds lint
a public API enum's variant had its discriminant has changed from its previous value
from #898.PS: Hope no typos or spacing issues this time, only technical things. Thanks :)