Skip to content

Commit 5b3a501

Browse files
[pylint] Avoid flattening nested min/max when outer call has single argument (PLW3301) (#16885)
## Summary Fixes false positives (and incorrect autofixes) in `nested-min-max` (`PLW3301`) when the outer `min`/`max` call only has a single argument. Previously the rule would flatten: ```python min(min([2, 3], [4, 1])) ``` into `min([2, 3], [4, 1])`, changing the semantics. The rule now skips any nested call when the outer call has only one positional argument. The pylint fixture and snapshot were updated accordingly. ## Test Plan Ran Ruff against the updated `nested_min_max.py` fixture: ```shell cargo run -p ruff -- check crates/ruff_linter/resources/test/fixtures/pylint/nested_min_max.py --no-cache --select=PLW3301 --preview ``` to verify that `min(min([2, 3], [4, 1]))` and `max(max([2, 4], [3, 1]))` are no longer flagged. Updated the fixture and snapshot; all other existing warnings remain unchanged. The code compiles and the unit tests pass. --- This PR was generated by an AI system in collaboration with maintainers: @carljm, @ntBre Fixes #16163 --------- Signed-off-by: Gene Parmesan Thomas <201852096+gopoto@users.noreply.github.com> Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
1 parent e66f182 commit 5b3a501

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

crates/ruff_linter/resources/test/fixtures/pylint/nested_min_max.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,8 @@
5555
*(len(word) for word in "blah blah blah".split(" ")),
5656
len("Done!"),
5757
)
58+
59+
60+
# Outer call has a single argument, inner call has multiple arguments; should not trigger.
61+
min(min([2, 3], [4, 1]))
62+
max(max([2, 4], [3, 1]))

crates/ruff_linter/src/rules/pylint/rules/nested_min_max.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,11 @@ pub(crate) fn nested_min_max(
155155
let Some(min_max) = MinMax::try_from_call(func, keywords, checker.semantic()) else {
156156
return;
157157
};
158-
159-
if matches!(&args, [Expr::Call(ast::ExprCall { arguments: Arguments {args, .. }, .. })] if args.len() == 1)
160-
{
158+
// It's only safe to flatten nested calls if the outer call has more than one argument.
159+
// When the outer call has a single argument, flattening would change the semantics by
160+
// changing the shape of the call from treating the inner result as an iterable (or a scalar)
161+
// to passing multiple arguments directly, which can lead to behavioral changes.
162+
if args.len() < 2 {
161163
return;
162164
}
163165

0 commit comments

Comments
 (0)