-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[refurb] FURB164 fix should validate arguments and should usually be marked unsafe
#19136
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
Conversation
|
ntBre
left a comment
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.
Thanks, this looks good to me. I just had some suggestions for simplifying the code a bit.
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
| } | ||
| MethodName::FromDecimal => { | ||
| // from_decimal(dec) - should have exactly one positional argument or 'dec' keyword | ||
| if call.arguments.args.len() == 1 && call.arguments.keywords.is_empty() { |
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.
Same as above, if it works above.
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
| // Must be a call to the `float` builtin. | ||
| if !checker.semantic().match_builtin_expr(func, "float") { | ||
| return None; |
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: I'd probably put this right after the let-else checking that it's a Call. I'm not sure which of these checks is most expensive, but that makes sense logically at least.
ntBre
left a comment
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.
Thanks! Just a few more slight simplifications.
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/refurb/rules/unnecessary_from_float.rs
Outdated
Show resolved
Hide resolved
…at.rs Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
…at.rs Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
…at.rs Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
…at.rs Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
…at.rs Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
Summary
Fixes #19076
An attempt at fixing #19076 where the rule could change program behavior by incorrectly converting from_float/from_decimal method calls to constructor calls.
The fix implements argument validation using Ruff's existing type inference system (
ResolvedPythonType,typing::is_int,typing::is_float) to determine when conversions are actually safe, adds logic to detect invalid method calls (wrong argument counts, incorrect keyword names) and suppress fixes for them, and changes the default fix applicability fromSafetoUnsafewith safe fixes only offered when the argument type is known to be compatible and no problematic keywords are used.One uncertainty is whether the type inference catches all possible edge cases in complex codebases, but the new approach is significantly more conservative and safer than the previous implementation.
Test Plan
I updated the existing test fixtures with edge cases from the issue and manually verified behavior with temporary test files for valid/unsafe/invalid scenarios.