Skip to content

Commit

Permalink
Make unnecessary-lambda an always-unsafe fix (#10668)
Browse files Browse the repository at this point in the history
## Summary

See the linked issue and comment for more.

Closes #10663.
  • Loading branch information
charliermarsh authored Mar 30, 2024
1 parent 7c2e9f7 commit fc54f53
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 18 deletions.
23 changes: 13 additions & 10 deletions crates/ruff_linter/src/rules/pylint/rules/unnecessary_lambda.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::contains_effect;
use ruff_python_ast::visitor::Visitor;
use ruff_python_ast::{self as ast, visitor, Expr, ExprLambda, Parameter, ParameterWithDefault};
use ruff_text_size::Ranged;
Expand All @@ -27,15 +26,23 @@ use crate::checkers::ast::Checker;
/// ```
///
/// ## Fix safety
/// This rule's fix is marked as unsafe in cases in which the lambda body itself
/// contains an effect.
/// This rule's fix is marked as unsafe for two primary reasons.
///
/// First, the lambda body itself could contain an effect.
///
/// For example, replacing `lambda x, y: (func()(x, y))` with `func()` would
/// lead to a change in behavior, as `func()` would be evaluated eagerly when
/// defining the lambda, rather than when the lambda is called.
///
/// When the lambda body contains no visible effects, the fix is considered
/// safe.
/// However, even when the lambda body itself is pure, the lambda may
/// change the argument names, which can lead to a change in behavior when
/// callers pass arguments by name.
///
/// For example, replacing `foo = lambda x, y: func(x, y)` with `foo = func`,
/// where `func` is defined as `def func(a, b): return a + b`, would be a
/// breaking change for callers that execute the lambda by passing arguments by
/// name, as in: `foo(x=1, y=2)`. Since `func` does not define the arguments
/// `x` and `y`, unlike the lambda, the call would raise a `TypeError`.
#[violation]
pub struct UnnecessaryLambda;

Expand Down Expand Up @@ -206,11 +213,7 @@ pub(crate) fn unnecessary_lambda(checker: &mut Checker, lambda: &ExprLambda) {
checker.locator().slice(func.as_ref()).to_string(),
lambda.range(),
),
if contains_effect(func.as_ref(), |id| checker.semantic().is_builtin(id)) {
Applicability::Unsafe
} else {
Applicability::Safe
},
Applicability::Unsafe,
));
checker.diagnostics.push(diagnostic);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ unnecessary_lambda.py:1:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
= help: Inline function call

Safe fix
Unsafe fix
1 |-_ = lambda: print() # [unnecessary-lambda]
1 |+_ = print # [unnecessary-lambda]
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
Expand All @@ -26,7 +26,7 @@ unnecessary_lambda.py:2:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
= help: Inline function call

Safe fix
Unsafe fix
1 1 | _ = lambda: print() # [unnecessary-lambda]
2 |-_ = lambda x, y: min(x, y) # [unnecessary-lambda]
2 |+_ = min # [unnecessary-lambda]
Expand All @@ -45,7 +45,7 @@ unnecessary_lambda.py:4:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
= help: Inline function call

Safe fix
Unsafe fix
1 1 | _ = lambda: print() # [unnecessary-lambda]
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
3 3 |
Expand All @@ -65,7 +65,7 @@ unnecessary_lambda.py:5:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
= help: Inline function call

Safe fix
Unsafe fix
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
3 3 |
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
Expand All @@ -85,7 +85,7 @@ unnecessary_lambda.py:6:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
= help: Inline function call

Safe fix
Unsafe fix
3 3 |
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
5 5 | _ = lambda **kwargs: f(**kwargs) # [unnecessary-lambda]
Expand All @@ -106,7 +106,7 @@ unnecessary_lambda.py:7:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
= help: Inline function call

Safe fix
Unsafe fix
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
5 5 | _ = lambda **kwargs: f(**kwargs) # [unnecessary-lambda]
6 6 | _ = lambda *args, **kwargs: f(*args, **kwargs) # [unnecessary-lambda]
Expand Down Expand Up @@ -155,5 +155,3 @@ unnecessary_lambda.py:10:5: PLW0108 [*] Lambda may be unnecessary; consider inli
11 11 |
12 12 | # default value in lambda parameters
13 13 | _ = lambda x=42: print(x)


0 comments on commit fc54f53

Please sign in to comment.