-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[ruff
] Mark RUF023
fix as unsafe if __slots__
is not a set and the binding is used elsewhere
#12692
Conversation
|
code | total | + violation | - violation | + fix | - fix |
---|---|---|---|---|---|
RUF023 | 6 | 0 | 0 | 0 | 6 |
…the binding is used elsewhere
5d9d758
to
e415ad3
Compare
I don’t think it is possible to know that the
which implies that |
Yeah -- I agree with all that @dscorbett. And by the same logic, we could also argue that the fix for RUF022 should always be marked as unsafe. I do however feel like it's pretty uncommon to iterate over the Overall I feel like this is a good compromise that reflects the fact that for arguably 99% of cases, this fix is safe if we can see that a class's
FWIW, I wrote that bullet point in the documentation ;-) |
To be clear: you may be right. This isn't an opinion I'm certain in; possibly this rule (and RUF022 as well?) should just have their autofixes marked as unsafe in nearly all instances. I'm interested to hear what other maintainers think here. (@carljm, maybe?) |
I don't think it's that hard to imagine a scenario where I also generally feel like we have unsafe fixes for a reason, and we should err on the side of marking fixes unsafe if there's a plausible scenario where they could break someone's code. ("Plausible" is of course doing a lot of heavy lifting there, and leaves a lot of room for debate.) I would probably mark this fix as unsafe, unless |
agreed -- but there is also a cost to marking a fix as unsafe. It means users don't get the autofix unless they either opt into all unsafe fixes (the |
The documentation for fix safety says “The meaning and intent of your code will be retained when applying safe fixes” but meaning and intent are hard to determine. Technically, no fix is 100% safe because a module’s source code can be inspected at runtime. That is an extreme case, of course; I’m just acknowledging that there’s always a trade-off. In the particular example with Maybe for edge cases (i.e. the fixes which this PR still marks as safe) it would be sufficient to mark the fix as safe but document in the rule’s “Fix safety” section that the fix is actually unsafe in certain circumstances. I leave to you all to determine where to draw the line in this case and how complex to make the check, but I hope the unsafety will be taken into account somewhere, whether code or documentation. |
Great suggestion. I pushed some more docs on fix safety -- for this rule and for RUF022 -- in 77bf580. |
if let Some(sorted_source_code) = display.generate_sorted_source_code(&items, checker) { | ||
let edit = Edit::range_replacement(sorted_source_code, display.range()); | ||
|
||
let applicability = if display.kind.is_set_literal() || !binding.is_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.
Nit nit: We may want to consider adding an is_unused
method. It reads more naturally
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.
Agreed -- but there's quite a few other places where we might consider using that method, so I'll propose it in a followup
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 #12729
…the binding is used elsewhere (astral-sh#12692)
Fixes #12653. This required a little bit of refactoring: in order to know whether the
__slots__
binding is used or not, the rule must run after the AST tree has been visited in its entirety; that meant that the rule's hook had to be moved out ofstatements.rs
and intobindings.rs
. This, in turn, meant that the function implementing the rule had to accept aBinding
rather than two AST nodes, and had to return anOption<Diagnostic>
rather than()
.