Skip to content

Commit 4fdd4dd

Browse files
authored
[ruff] Don't emit used-dummy-variable on function parameters (RUF052) (#14818)
1 parent 6b9f3d7 commit 4fdd4dd

5 files changed

+23
-112
lines changed

crates/ruff_linter/resources/test/fixtures/ruff/RUF052.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def fun(self):
7777
_var = "method variable" # [RUF052]
7878
return _var
7979

80-
def fun(_var): # [RUF052]
80+
def fun(_var): # parameters are ignored
8181
return _var
8282

8383
def fun():

crates/ruff_linter/src/rules/ruff/rules/used_dummy_variable.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
22
use ruff_macros::{derive_message_formats, ViolationMetadata};
33
use ruff_python_ast::helpers::is_dunder;
4-
use ruff_python_semantic::{Binding, BindingKind, ScopeId};
4+
use ruff_python_semantic::{Binding, ScopeId};
55
use ruff_python_stdlib::{
66
builtins::is_python_builtin, identifiers::is_identifier, keyword::is_keyword,
77
};
@@ -93,13 +93,27 @@ pub(crate) fn used_dummy_variable(checker: &Checker, binding: &Binding) -> Optio
9393
if binding.is_unused() {
9494
return None;
9595
}
96-
// Only variables defined via function arguments or assignments.
97-
if !matches!(
98-
binding.kind,
99-
BindingKind::Argument | BindingKind::Assignment
100-
) {
96+
97+
// We only emit the lint on variables defined via assignments.
98+
//
99+
// ## Why not also emit the lint on function parameters?
100+
//
101+
// There isn't universal agreement that leading underscores indicate "unused" parameters
102+
// in Python (many people use them for "private" parameters), so this would be a lot more
103+
// controversial than emitting the lint on assignments. Even if it's decided that it's
104+
// desirable to emit a lint on function parameters with "dummy variable" names, it would
105+
// possibly have to be a separate rule or we'd have to put it behind a configuration flag,
106+
// as there's much less community consensus about the issue.
107+
// See <https://github.com/astral-sh/ruff/issues/14796>.
108+
//
109+
// Moreover, autofixing the diagnostic for function parameters is much more troublesome than
110+
// autofixing the diagnostic for assignments. See:
111+
// - <https://github.com/astral-sh/ruff/issues/14790>
112+
// - <https://github.com/astral-sh/ruff/issues/14799>
113+
if !binding.kind.is_assignment() {
101114
return None;
102115
}
116+
103117
// This excludes `global` and `nonlocal` variables.
104118
if binding.is_global() || binding.is_nonlocal() {
105119
return None;

crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF052_RUF052.py.snap

+1-23
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,9 @@ RUF052.py:77:9: RUF052 [*] Local dummy variable `_var` is accessed
2020
77 |+ var = "method variable" # [RUF052]
2121
78 |+ return var
2222
79 79 |
23-
80 80 | def fun(_var): # [RUF052]
23+
80 80 | def fun(_var): # parameters are ignored
2424
81 81 | return _var
2525

26-
RUF052.py:80:9: RUF052 [*] Local dummy variable `_var` is accessed
27-
|
28-
78 | return _var
29-
79 |
30-
80 | def fun(_var): # [RUF052]
31-
| ^^^^ RUF052
32-
81 | return _var
33-
|
34-
= help: Remove leading underscores
35-
36-
Safe fix
37-
77 77 | _var = "method variable" # [RUF052]
38-
78 78 | return _var
39-
79 79 |
40-
80 |-def fun(_var): # [RUF052]
41-
81 |- return _var
42-
80 |+def fun(var): # [RUF052]
43-
81 |+ return var
44-
82 82 |
45-
83 83 | def fun():
46-
84 84 | _list = "built-in" # [RUF052]
47-
4826
RUF052.py:84:5: RUF052 [*] Local dummy variable `_list` is accessed
4927
|
5028
83 | def fun():

crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__custom_dummy_var_regexp_preset__RUF052_RUF052.py_1.snap

+1-23
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,9 @@ RUF052.py:77:9: RUF052 [*] Local dummy variable `_var` is accessed
2020
77 |+ var = "method variable" # [RUF052]
2121
78 |+ return var
2222
79 79 |
23-
80 80 | def fun(_var): # [RUF052]
23+
80 80 | def fun(_var): # parameters are ignored
2424
81 81 | return _var
2525

26-
RUF052.py:80:9: RUF052 [*] Local dummy variable `_var` is accessed
27-
|
28-
78 | return _var
29-
79 |
30-
80 | def fun(_var): # [RUF052]
31-
| ^^^^ RUF052
32-
81 | return _var
33-
|
34-
= help: Remove leading underscores
35-
36-
Safe fix
37-
77 77 | _var = "method variable" # [RUF052]
38-
78 78 | return _var
39-
79 79 |
40-
80 |-def fun(_var): # [RUF052]
41-
81 |- return _var
42-
80 |+def fun(var): # [RUF052]
43-
81 |+ return var
44-
82 82 |
45-
83 83 | def fun():
46-
84 84 | _list = "built-in" # [RUF052]
47-
4826
RUF052.py:84:5: RUF052 [*] Local dummy variable `_list` is accessed
4927
|
5028
83 | def fun():

crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__custom_dummy_var_regexp_preset__RUF052_RUF052.py_2.snap

-59
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,6 @@
11
---
22
source: crates/ruff_linter/src/rules/ruff/mod.rs
33
---
4-
RUF052.py:21:9: RUF052 Local dummy variable `arg` is accessed
5-
|
6-
19 | _valid_fun()
7-
20 |
8-
21 | def fun(arg):
9-
| ^^^ RUF052
10-
22 | _valid_unused_var = arg
11-
23 | pass
12-
|
13-
14-
RUF052.py:50:18: RUF052 Local dummy variable `self` is accessed
15-
|
16-
48 | print(_valid_private_cls_attr)
17-
49 |
18-
50 | def __init__(self):
19-
| ^^^^ RUF052
20-
51 | self._valid_private_ins_attr = 2
21-
52 | print(self._valid_private_ins_attr)
22-
|
23-
24-
RUF052.py:54:23: RUF052 Local dummy variable `self` is accessed
25-
|
26-
52 | print(self._valid_private_ins_attr)
27-
53 |
28-
54 | def _valid_method(self):
29-
| ^^^^ RUF052
30-
55 | return self._valid_private_ins_attr
31-
|
32-
33-
RUF052.py:57:16: RUF052 Local dummy variable `arg` is accessed
34-
|
35-
55 | return self._valid_private_ins_attr
36-
56 |
37-
57 | def method(arg):
38-
| ^^^ RUF052
39-
58 | _valid_unused_var = arg
40-
59 | return
41-
|
42-
43-
RUF052.py:61:9: RUF052 Local dummy variable `x` is accessed
44-
|
45-
59 | return
46-
60 |
47-
61 | def fun(x):
48-
| ^ RUF052
49-
62 | _ = 1
50-
63 | __ = 2
51-
|
52-
534
RUF052.py:77:9: RUF052 Local dummy variable `_var` is accessed
545
|
556
75 | class Class_:
@@ -60,16 +11,6 @@ RUF052.py:77:9: RUF052 Local dummy variable `_var` is accessed
6011
|
6112
= help: Remove leading underscores
6213

63-
RUF052.py:80:9: RUF052 Local dummy variable `_var` is accessed
64-
|
65-
78 | return _var
66-
79 |
67-
80 | def fun(_var): # [RUF052]
68-
| ^^^^ RUF052
69-
81 | return _var
70-
|
71-
= help: Remove leading underscores
72-
7314
RUF052.py:84:5: RUF052 Local dummy variable `_list` is accessed
7415
|
7516
83 | def fun():

0 commit comments

Comments
 (0)