mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:24 +00:00
Make unnecessary-lambda
an always-unsafe fix (#10668)
## Summary See the linked issue and comment for more. Closes https://github.com/astral-sh/ruff/issues/10663.
This commit is contained in:
parent
7c2e9f71ea
commit
fc54f53662
2 changed files with 19 additions and 18 deletions
|
@ -1,6 +1,5 @@
|
||||||
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::contains_effect;
|
|
||||||
use ruff_python_ast::visitor::Visitor;
|
use ruff_python_ast::visitor::Visitor;
|
||||||
use ruff_python_ast::{self as ast, visitor, Expr, ExprLambda, Parameter, ParameterWithDefault};
|
use ruff_python_ast::{self as ast, visitor, Expr, ExprLambda, Parameter, ParameterWithDefault};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
@ -27,15 +26,23 @@ use crate::checkers::ast::Checker;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Fix safety
|
/// ## Fix safety
|
||||||
/// This rule's fix is marked as unsafe in cases in which the lambda body itself
|
/// This rule's fix is marked as unsafe for two primary reasons.
|
||||||
/// contains an effect.
|
///
|
||||||
|
/// First, the lambda body itself could contain an effect.
|
||||||
///
|
///
|
||||||
/// For example, replacing `lambda x, y: (func()(x, y))` with `func()` would
|
/// 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
|
/// lead to a change in behavior, as `func()` would be evaluated eagerly when
|
||||||
/// defining the lambda, rather than when the lambda is called.
|
/// defining the lambda, rather than when the lambda is called.
|
||||||
///
|
///
|
||||||
/// When the lambda body contains no visible effects, the fix is considered
|
/// However, even when the lambda body itself is pure, the lambda may
|
||||||
/// safe.
|
/// 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]
|
#[violation]
|
||||||
pub struct UnnecessaryLambda;
|
pub struct UnnecessaryLambda;
|
||||||
|
|
||||||
|
@ -206,11 +213,7 @@ pub(crate) fn unnecessary_lambda(checker: &mut Checker, lambda: &ExprLambda) {
|
||||||
checker.locator().slice(func.as_ref()).to_string(),
|
checker.locator().slice(func.as_ref()).to_string(),
|
||||||
lambda.range(),
|
lambda.range(),
|
||||||
),
|
),
|
||||||
if contains_effect(func.as_ref(), |id| checker.semantic().is_builtin(id)) {
|
Applicability::Unsafe,
|
||||||
Applicability::Unsafe
|
|
||||||
} else {
|
|
||||||
Applicability::Safe
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ unnecessary_lambda.py:1:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
||||||
|
|
|
|
||||||
= help: Inline function call
|
= help: Inline function call
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Unsafe fix
|
||||||
1 |-_ = lambda: print() # [unnecessary-lambda]
|
1 |-_ = lambda: print() # [unnecessary-lambda]
|
||||||
1 |+_ = print # [unnecessary-lambda]
|
1 |+_ = print # [unnecessary-lambda]
|
||||||
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
||||||
|
@ -26,7 +26,7 @@ unnecessary_lambda.py:2:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
||||||
|
|
|
|
||||||
= help: Inline function call
|
= help: Inline function call
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Unsafe fix
|
||||||
1 1 | _ = lambda: print() # [unnecessary-lambda]
|
1 1 | _ = lambda: print() # [unnecessary-lambda]
|
||||||
2 |-_ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
2 |-_ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
||||||
2 |+_ = min # [unnecessary-lambda]
|
2 |+_ = min # [unnecessary-lambda]
|
||||||
|
@ -45,7 +45,7 @@ unnecessary_lambda.py:4:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
||||||
|
|
|
|
||||||
= help: Inline function call
|
= help: Inline function call
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Unsafe fix
|
||||||
1 1 | _ = lambda: print() # [unnecessary-lambda]
|
1 1 | _ = lambda: print() # [unnecessary-lambda]
|
||||||
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
||||||
3 3 |
|
3 3 |
|
||||||
|
@ -65,7 +65,7 @@ unnecessary_lambda.py:5:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
||||||
|
|
|
|
||||||
= help: Inline function call
|
= help: Inline function call
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Unsafe fix
|
||||||
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
2 2 | _ = lambda x, y: min(x, y) # [unnecessary-lambda]
|
||||||
3 3 |
|
3 3 |
|
||||||
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
|
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
|
||||||
|
@ -85,7 +85,7 @@ unnecessary_lambda.py:6:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
||||||
|
|
|
|
||||||
= help: Inline function call
|
= help: Inline function call
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Unsafe fix
|
||||||
3 3 |
|
3 3 |
|
||||||
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
|
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
|
||||||
5 5 | _ = lambda **kwargs: f(**kwargs) # [unnecessary-lambda]
|
5 5 | _ = lambda **kwargs: f(**kwargs) # [unnecessary-lambda]
|
||||||
|
@ -106,7 +106,7 @@ unnecessary_lambda.py:7:5: PLW0108 [*] Lambda may be unnecessary; consider inlin
|
||||||
|
|
|
|
||||||
= help: Inline function call
|
= help: Inline function call
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Unsafe fix
|
||||||
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
|
4 4 | _ = lambda *args: f(*args) # [unnecessary-lambda]
|
||||||
5 5 | _ = lambda **kwargs: f(**kwargs) # [unnecessary-lambda]
|
5 5 | _ = lambda **kwargs: f(**kwargs) # [unnecessary-lambda]
|
||||||
6 6 | _ = lambda *args, **kwargs: f(*args, **kwargs) # [unnecessary-lambda]
|
6 6 | _ = lambda *args, **kwargs: f(*args, **kwargs) # [unnecessary-lambda]
|
||||||
|
@ -155,5 +155,3 @@ unnecessary_lambda.py:10:5: PLW0108 [*] Lambda may be unnecessary; consider inli
|
||||||
11 11 |
|
11 11 |
|
||||||
12 12 | # default value in lambda parameters
|
12 12 | # default value in lambda parameters
|
||||||
13 13 | _ = lambda x=42: print(x)
|
13 13 | _ = lambda x=42: print(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue