[flake8_pyi] Fix PYI041's fix causing TypeError with None | None | ... (#18637)

<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary
Fix `PYI041`'s fix turning `None | int | None | float` into `None | None
| float`, which raises a `TypeError` when executed.

The fix consists of making sure that the merged super-type is inserted
where the first type that is merged was before.

## Test Plan
Tests have been expanded with examples from the issue.

## Related Issue
Fixes https://github.com/astral-sh/ruff/issues/18298
This commit is contained in:
Robsdedude 2025-06-20 19:04:51 +00:00 committed by GitHub
parent 49763a7f7c
commit e36611c4d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 482 additions and 330 deletions

View file

@ -1,4 +1,5 @@
from typing import (
TYPE_CHECKING,
Union,
)
@ -90,3 +91,22 @@ class Foo:
def bad5(self, arg: int | (float | complex)) -> None:
...
# https://github.com/astral-sh/ruff/issues/18298
# fix must not yield runtime `None | None | ...` (TypeError)
class Issue18298:
def f1(self, arg: None | int | None | float = None) -> None: # PYI041 - no fix
pass
if TYPE_CHECKING:
def f2(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
else:
def f2(self, arg=None) -> None:
pass
def f3(self, arg: None | float | None | int | None = None) -> None: # PYI041 - with fix
pass

View file

@ -70,3 +70,11 @@ class Foo:
def bad4(self, arg: Union[float | complex, int]) -> None: ... # PYI041
def bad5(self, arg: int | (float | complex)) -> None: ... # PYI041
# https://github.com/astral-sh/ruff/issues/18298
# fix must not yield runtime `None | None | ...` (TypeError)
class Issue18298:
def f1(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
def f3(self, arg: None | float | None | int | None = None) -> None: ... # PYI041 - with fix

View file

@ -0,0 +1,8 @@
from __future__ import annotations
# https://github.com/astral-sh/ruff/issues/18298
# fix must not yield runtime `None | None | ...` (TypeError)
class Issue18298:
def f1(self, arg: None | int | None | float = None) -> None:
pass

View file

@ -72,8 +72,9 @@ mod tests {
#[test_case(Rule::RedundantFinalLiteral, Path::new("PYI064.pyi"))]
#[test_case(Rule::RedundantLiteralUnion, Path::new("PYI051.py"))]
#[test_case(Rule::RedundantLiteralUnion, Path::new("PYI051.pyi"))]
#[test_case(Rule::RedundantNumericUnion, Path::new("PYI041.py"))]
#[test_case(Rule::RedundantNumericUnion, Path::new("PYI041.pyi"))]
#[test_case(Rule::RedundantNumericUnion, Path::new("PYI041_1.py"))]
#[test_case(Rule::RedundantNumericUnion, Path::new("PYI041_1.pyi"))]
#[test_case(Rule::RedundantNumericUnion, Path::new("PYI041_2.py"))]
#[test_case(Rule::SnakeCaseTypeAlias, Path::new("PYI042.py"))]
#[test_case(Rule::SnakeCaseTypeAlias, Path::new("PYI042.pyi"))]
#[test_case(Rule::StrOrReprDefinedInStub, Path::new("PYI029.py"))]

View file

@ -132,6 +132,15 @@ fn check_annotation<'a>(checker: &Checker, annotation: &'a Expr) {
let mut diagnostic =
checker.report_diagnostic(RedundantNumericUnion { redundancy }, annotation.range());
if !checker.semantic().execution_context().is_typing()
&& !checker.source_type.is_stub()
&& fix_starts_with_none_none(&necessary_nodes)
{
// If there are multiple `None` literals, we cannot apply the fix in a runtime context.
// E.g., `None | None | int` will cause a `RuntimeError`.
return;
}
// Mark [`Fix`] as unsafe when comments are in range.
let applicability = if checker.comment_ranges().intersects(annotation.range()) {
Applicability::Unsafe
@ -265,3 +274,8 @@ fn generate_pep604_fix(
applicability,
)
}
/// Check whether the proposed fix starts with two `None` literals.
fn fix_starts_with_none_none(nodes: &[&Expr]) -> bool {
nodes.len() >= 2 && nodes.iter().take(2).all(|node| node.is_none_literal_expr())
}

View file

@ -1,311 +0,0 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
snapshot_kind: text
---
PYI041.py:22:14: PYI041 [*] Use `float` instead of `int | float`
|
22 | def f0(arg1: float | int) -> None:
| ^^^^^^^^^^^ PYI041
23 | ...
|
= help: Remove redundant type
Safe fix
19 19 | ...
20 20 |
21 21 |
22 |-def f0(arg1: float | int) -> None:
22 |+def f0(arg1: float) -> None:
23 23 | ...
24 24 |
25 25 |
PYI041.py:26:30: PYI041 [*] Use `complex` instead of `float | complex`
|
26 | def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
27 | ...
|
= help: Remove redundant type
Safe fix
23 23 | ...
24 24 |
25 25 |
26 |-def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None:
26 |+def f1(arg1: float, *, arg2: list[str] | type[bool] | complex) -> None:
27 27 | ...
28 28 |
29 29 |
PYI041.py:30:28: PYI041 [*] Use `float` instead of `int | float`
|
30 | def f2(arg1: int, /, arg2: int | int | float) -> None:
| ^^^^^^^^^^^^^^^^^ PYI041
31 | ...
|
= help: Remove redundant type
Safe fix
27 27 | ...
28 28 |
29 29 |
30 |-def f2(arg1: int, /, arg2: int | int | float) -> None:
30 |+def f2(arg1: int, /, arg2: float) -> None:
31 31 | ...
32 32 |
33 33 |
PYI041.py:34:26: PYI041 [*] Use `float` instead of `int | float`
|
34 | def f3(arg1: int, *args: Union[int | int | float]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
35 | ...
|
= help: Remove redundant type
Safe fix
31 31 | ...
32 32 |
33 33 |
34 |-def f3(arg1: int, *args: Union[int | int | float]) -> None:
34 |+def f3(arg1: int, *args: float) -> None:
35 35 | ...
36 36 |
37 37 |
PYI041.py:38:24: PYI041 [*] Use `float` instead of `int | float`
|
38 | async def f4(**kwargs: int | int | float) -> None:
| ^^^^^^^^^^^^^^^^^ PYI041
39 | ...
|
= help: Remove redundant type
Safe fix
35 35 | ...
36 36 |
37 37 |
38 |-async def f4(**kwargs: int | int | float) -> None:
38 |+async def f4(**kwargs: float) -> None:
39 39 | ...
40 40 |
41 41 |
PYI041.py:42:26: PYI041 [*] Use `float` instead of `int | float`
|
42 | def f5(arg1: int, *args: Union[int, int, float]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^ PYI041
43 | ...
|
= help: Remove redundant type
Safe fix
39 39 | ...
40 40 |
41 41 |
42 |-def f5(arg1: int, *args: Union[int, int, float]) -> None:
42 |+def f5(arg1: int, *args: float) -> None:
43 43 | ...
44 44 |
45 45 |
PYI041.py:46:26: PYI041 [*] Use `float` instead of `int | float`
|
46 | def f6(arg1: int, *args: Union[Union[int, int, float]]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
47 | ...
|
= help: Remove redundant type
Safe fix
43 43 | ...
44 44 |
45 45 |
46 |-def f6(arg1: int, *args: Union[Union[int, int, float]]) -> None:
46 |+def f6(arg1: int, *args: float) -> None:
47 47 | ...
48 48 |
49 49 |
PYI041.py:50:26: PYI041 [*] Use `float` instead of `int | float`
|
50 | def f7(arg1: int, *args: Union[Union[Union[int, int, float]]]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
51 | ...
|
= help: Remove redundant type
Safe fix
47 47 | ...
48 48 |
49 49 |
50 |-def f7(arg1: int, *args: Union[Union[Union[int, int, float]]]) -> None:
50 |+def f7(arg1: int, *args: float) -> None:
51 51 | ...
52 52 |
53 53 |
PYI041.py:54:26: PYI041 [*] Use `float` instead of `int | float`
|
54 | def f8(arg1: int, *args: Union[Union[Union[int | int | float]]]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
55 | ...
|
= help: Remove redundant type
Safe fix
51 51 | ...
52 52 |
53 53 |
54 |-def f8(arg1: int, *args: Union[Union[Union[int | int | float]]]) -> None:
54 |+def f8(arg1: int, *args: float) -> None:
55 55 | ...
56 56 |
57 57 |
PYI041.py:59:10: PYI041 [*] Use `complex` instead of `int | float | complex`
|
58 | def f9(
59 | arg: Union[ # comment
| __________^
60 | | float, # another
61 | | complex, int]
| |_____________________^ PYI041
62 | ) -> None:
63 | ...
|
= help: Remove redundant type
Unsafe fix
56 56 |
57 57 |
58 58 | def f9(
59 |- arg: Union[ # comment
60 |- float, # another
61 |- complex, int]
59 |+ arg: complex
62 60 | ) -> None:
63 61 | ...
64 62 |
PYI041.py:67:9: PYI041 [*] Use `complex` instead of `int | float | complex`
|
65 | def f10(
66 | arg: (
67 | / int | # comment
68 | | float | # another
69 | | complex
| |_______________^ PYI041
70 | )
71 | ) -> None:
|
= help: Remove redundant type
Unsafe fix
64 64 |
65 65 | def f10(
66 66 | arg: (
67 |- int | # comment
68 |- float | # another
69 67 | complex
70 68 | )
71 69 | ) -> None:
PYI041.py:79:24: PYI041 [*] Use `complex` instead of `int | float | complex`
|
77 | ...
78 |
79 | def bad(self, arg: int | float | complex) -> None:
| ^^^^^^^^^^^^^^^^^^^^^ PYI041
80 | ...
|
= help: Remove redundant type
Safe fix
76 76 | def good(self, arg: int) -> None:
77 77 | ...
78 78 |
79 |- def bad(self, arg: int | float | complex) -> None:
79 |+ def bad(self, arg: complex) -> None:
80 80 | ...
81 81 |
82 82 | def bad2(self, arg: int | Union[float, complex]) -> None:
PYI041.py:82:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
80 | ...
81 |
82 | def bad2(self, arg: int | Union[float, complex]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
83 | ...
|
= help: Remove redundant type
Safe fix
79 79 | def bad(self, arg: int | float | complex) -> None:
80 80 | ...
81 81 |
82 |- def bad2(self, arg: int | Union[float, complex]) -> None:
82 |+ def bad2(self, arg: complex) -> None:
83 83 | ...
84 84 |
85 85 | def bad3(self, arg: Union[Union[float, complex], int]) -> None:
PYI041.py:85:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
83 | ...
84 |
85 | def bad3(self, arg: Union[Union[float, complex], int]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
86 | ...
|
= help: Remove redundant type
Safe fix
82 82 | def bad2(self, arg: int | Union[float, complex]) -> None:
83 83 | ...
84 84 |
85 |- def bad3(self, arg: Union[Union[float, complex], int]) -> None:
85 |+ def bad3(self, arg: complex) -> None:
86 86 | ...
87 87 |
88 88 | def bad4(self, arg: Union[float | complex, int]) -> None:
PYI041.py:88:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
86 | ...
87 |
88 | def bad4(self, arg: Union[float | complex, int]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
89 | ...
|
= help: Remove redundant type
Safe fix
85 85 | def bad3(self, arg: Union[Union[float, complex], int]) -> None:
86 86 | ...
87 87 |
88 |- def bad4(self, arg: Union[float | complex, int]) -> None:
88 |+ def bad4(self, arg: complex) -> None:
89 89 | ...
90 90 |
91 91 | def bad5(self, arg: int | (float | complex)) -> None:
PYI041.py:91:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
89 | ...
90 |
91 | def bad5(self, arg: int | (float | complex)) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI041
92 | ...
|
= help: Remove redundant type
Safe fix
88 88 | def bad4(self, arg: Union[float | complex, int]) -> None:
89 89 | ...
90 90 |
91 |- def bad5(self, arg: int | (float | complex)) -> None:
91 |+ def bad5(self, arg: complex) -> None:
92 92 | ...

View file

@ -0,0 +1,361 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
---
PYI041_1.py:23:14: PYI041 [*] Use `float` instead of `int | float`
|
23 | def f0(arg1: float | int) -> None:
| ^^^^^^^^^^^ PYI041
24 | ...
|
= help: Remove redundant type
Safe fix
20 20 | ...
21 21 |
22 22 |
23 |-def f0(arg1: float | int) -> None:
23 |+def f0(arg1: float) -> None:
24 24 | ...
25 25 |
26 26 |
PYI041_1.py:27:30: PYI041 [*] Use `complex` instead of `float | complex`
|
27 | def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
28 | ...
|
= help: Remove redundant type
Safe fix
24 24 | ...
25 25 |
26 26 |
27 |-def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None:
27 |+def f1(arg1: float, *, arg2: list[str] | type[bool] | complex) -> None:
28 28 | ...
29 29 |
30 30 |
PYI041_1.py:31:28: PYI041 [*] Use `float` instead of `int | float`
|
31 | def f2(arg1: int, /, arg2: int | int | float) -> None:
| ^^^^^^^^^^^^^^^^^ PYI041
32 | ...
|
= help: Remove redundant type
Safe fix
28 28 | ...
29 29 |
30 30 |
31 |-def f2(arg1: int, /, arg2: int | int | float) -> None:
31 |+def f2(arg1: int, /, arg2: float) -> None:
32 32 | ...
33 33 |
34 34 |
PYI041_1.py:35:26: PYI041 [*] Use `float` instead of `int | float`
|
35 | def f3(arg1: int, *args: Union[int | int | float]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
36 | ...
|
= help: Remove redundant type
Safe fix
32 32 | ...
33 33 |
34 34 |
35 |-def f3(arg1: int, *args: Union[int | int | float]) -> None:
35 |+def f3(arg1: int, *args: float) -> None:
36 36 | ...
37 37 |
38 38 |
PYI041_1.py:39:24: PYI041 [*] Use `float` instead of `int | float`
|
39 | async def f4(**kwargs: int | int | float) -> None:
| ^^^^^^^^^^^^^^^^^ PYI041
40 | ...
|
= help: Remove redundant type
Safe fix
36 36 | ...
37 37 |
38 38 |
39 |-async def f4(**kwargs: int | int | float) -> None:
39 |+async def f4(**kwargs: float) -> None:
40 40 | ...
41 41 |
42 42 |
PYI041_1.py:43:26: PYI041 [*] Use `float` instead of `int | float`
|
43 | def f5(arg1: int, *args: Union[int, int, float]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^ PYI041
44 | ...
|
= help: Remove redundant type
Safe fix
40 40 | ...
41 41 |
42 42 |
43 |-def f5(arg1: int, *args: Union[int, int, float]) -> None:
43 |+def f5(arg1: int, *args: float) -> None:
44 44 | ...
45 45 |
46 46 |
PYI041_1.py:47:26: PYI041 [*] Use `float` instead of `int | float`
|
47 | def f6(arg1: int, *args: Union[Union[int, int, float]]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
48 | ...
|
= help: Remove redundant type
Safe fix
44 44 | ...
45 45 |
46 46 |
47 |-def f6(arg1: int, *args: Union[Union[int, int, float]]) -> None:
47 |+def f6(arg1: int, *args: float) -> None:
48 48 | ...
49 49 |
50 50 |
PYI041_1.py:51:26: PYI041 [*] Use `float` instead of `int | float`
|
51 | def f7(arg1: int, *args: Union[Union[Union[int, int, float]]]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
52 | ...
|
= help: Remove redundant type
Safe fix
48 48 | ...
49 49 |
50 50 |
51 |-def f7(arg1: int, *args: Union[Union[Union[int, int, float]]]) -> None:
51 |+def f7(arg1: int, *args: float) -> None:
52 52 | ...
53 53 |
54 54 |
PYI041_1.py:55:26: PYI041 [*] Use `float` instead of `int | float`
|
55 | def f8(arg1: int, *args: Union[Union[Union[int | int | float]]]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
56 | ...
|
= help: Remove redundant type
Safe fix
52 52 | ...
53 53 |
54 54 |
55 |-def f8(arg1: int, *args: Union[Union[Union[int | int | float]]]) -> None:
55 |+def f8(arg1: int, *args: float) -> None:
56 56 | ...
57 57 |
58 58 |
PYI041_1.py:60:10: PYI041 [*] Use `complex` instead of `int | float | complex`
|
59 | def f9(
60 | arg: Union[ # comment
| __________^
61 | | float, # another
62 | | complex, int]
| |_____________________^ PYI041
63 | ) -> None:
64 | ...
|
= help: Remove redundant type
Unsafe fix
57 57 |
58 58 |
59 59 | def f9(
60 |- arg: Union[ # comment
61 |- float, # another
62 |- complex, int]
60 |+ arg: complex
63 61 | ) -> None:
64 62 | ...
65 63 |
PYI041_1.py:68:9: PYI041 [*] Use `complex` instead of `int | float | complex`
|
66 | def f10(
67 | arg: (
68 | / int | # comment
69 | | float | # another
70 | | complex
| |_______________^ PYI041
71 | )
72 | ) -> None:
|
= help: Remove redundant type
Unsafe fix
65 65 |
66 66 | def f10(
67 67 | arg: (
68 |- int | # comment
69 |- float | # another
70 68 | complex
71 69 | )
72 70 | ) -> None:
PYI041_1.py:80:24: PYI041 [*] Use `complex` instead of `int | float | complex`
|
78 | ...
79 |
80 | def bad(self, arg: int | float | complex) -> None:
| ^^^^^^^^^^^^^^^^^^^^^ PYI041
81 | ...
|
= help: Remove redundant type
Safe fix
77 77 | def good(self, arg: int) -> None:
78 78 | ...
79 79 |
80 |- def bad(self, arg: int | float | complex) -> None:
80 |+ def bad(self, arg: complex) -> None:
81 81 | ...
82 82 |
83 83 | def bad2(self, arg: int | Union[float, complex]) -> None:
PYI041_1.py:83:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
81 | ...
82 |
83 | def bad2(self, arg: int | Union[float, complex]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
84 | ...
|
= help: Remove redundant type
Safe fix
80 80 | def bad(self, arg: int | float | complex) -> None:
81 81 | ...
82 82 |
83 |- def bad2(self, arg: int | Union[float, complex]) -> None:
83 |+ def bad2(self, arg: complex) -> None:
84 84 | ...
85 85 |
86 86 | def bad3(self, arg: Union[Union[float, complex], int]) -> None:
PYI041_1.py:86:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
84 | ...
85 |
86 | def bad3(self, arg: Union[Union[float, complex], int]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
87 | ...
|
= help: Remove redundant type
Safe fix
83 83 | def bad2(self, arg: int | Union[float, complex]) -> None:
84 84 | ...
85 85 |
86 |- def bad3(self, arg: Union[Union[float, complex], int]) -> None:
86 |+ def bad3(self, arg: complex) -> None:
87 87 | ...
88 88 |
89 89 | def bad4(self, arg: Union[float | complex, int]) -> None:
PYI041_1.py:89:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
87 | ...
88 |
89 | def bad4(self, arg: Union[float | complex, int]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
90 | ...
|
= help: Remove redundant type
Safe fix
86 86 | def bad3(self, arg: Union[Union[float, complex], int]) -> None:
87 87 | ...
88 88 |
89 |- def bad4(self, arg: Union[float | complex, int]) -> None:
89 |+ def bad4(self, arg: complex) -> None:
90 90 | ...
91 91 |
92 92 | def bad5(self, arg: int | (float | complex)) -> None:
PYI041_1.py:92:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
90 | ...
91 |
92 | def bad5(self, arg: int | (float | complex)) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI041
93 | ...
|
= help: Remove redundant type
Safe fix
89 89 | def bad4(self, arg: Union[float | complex, int]) -> None:
90 90 | ...
91 91 |
92 |- def bad5(self, arg: int | (float | complex)) -> None:
92 |+ def bad5(self, arg: complex) -> None:
93 93 | ...
94 94 |
95 95 |
PYI041_1.py:99:23: PYI041 Use `float` instead of `int | float`
|
97 | # fix must not yield runtime `None | None | ...` (TypeError)
98 | class Issue18298:
99 | def f1(self, arg: None | int | None | float = None) -> None: # PYI041 - no fix
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
100 | pass
|
= help: Remove redundant type
PYI041_1.py:104:27: PYI041 [*] Use `float` instead of `int | float`
|
102 | if TYPE_CHECKING:
103 |
104 | def f2(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
105 |
106 | else:
|
= help: Remove redundant type
Safe fix
101 101 |
102 102 | if TYPE_CHECKING:
103 103 |
104 |- def f2(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
104 |+ def f2(self, arg: None | None | float = None) -> None: ... # PYI041 - with fix
105 105 |
106 106 | else:
107 107 |
PYI041_1.py:111:23: PYI041 [*] Use `float` instead of `int | float`
|
109 | pass
110 |
111 | def f3(self, arg: None | float | None | int | None = None) -> None: # PYI041 - with fix
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
112 | pass
|
= help: Remove redundant type
Safe fix
108 108 | def f2(self, arg=None) -> None:
109 109 | pass
110 110 |
111 |- def f3(self, arg: None | float | None | int | None = None) -> None: # PYI041 - with fix
111 |+ def f3(self, arg: None | float | None | None = None) -> None: # PYI041 - with fix
112 112 | pass

View file

@ -1,8 +1,7 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
snapshot_kind: text
---
PYI041.pyi:21:14: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:21:14: PYI041 [*] Use `float` instead of `int | float`
|
21 | def f0(arg1: float | int) -> None: ... # PYI041
| ^^^^^^^^^^^ PYI041
@ -19,7 +18,7 @@ PYI041.pyi:21:14: PYI041 [*] Use `float` instead of `int | float`
23 23 |
24 24 | def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None: ... # PYI041
PYI041.pyi:24:30: PYI041 [*] Use `complex` instead of `float | complex`
PYI041_1.pyi:24:30: PYI041 [*] Use `complex` instead of `float | complex`
|
24 | def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
@ -36,7 +35,7 @@ PYI041.pyi:24:30: PYI041 [*] Use `complex` instead of `float | complex`
26 26 |
27 27 | def f2(arg1: int, /, arg2: int | int | float) -> None: ... # PYI041
PYI041.pyi:27:28: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:27:28: PYI041 [*] Use `float` instead of `int | float`
|
27 | def f2(arg1: int, /, arg2: int | int | float) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^ PYI041
@ -53,7 +52,7 @@ PYI041.pyi:27:28: PYI041 [*] Use `float` instead of `int | float`
29 29 |
30 30 | def f3(arg1: int, *args: Union[int | int | float]) -> None: ... # PYI041
PYI041.pyi:30:26: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:30:26: PYI041 [*] Use `float` instead of `int | float`
|
30 | def f3(arg1: int, *args: Union[int | int | float]) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
@ -70,7 +69,7 @@ PYI041.pyi:30:26: PYI041 [*] Use `float` instead of `int | float`
32 32 |
33 33 | async def f4(**kwargs: int | int | float) -> None: ... # PYI041
PYI041.pyi:33:24: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:33:24: PYI041 [*] Use `float` instead of `int | float`
|
33 | async def f4(**kwargs: int | int | float) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^ PYI041
@ -89,7 +88,7 @@ PYI041.pyi:33:24: PYI041 [*] Use `float` instead of `int | float`
35 35 | def f5(
36 36 | arg: Union[ # comment
PYI041.pyi:36:10: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:36:10: PYI041 [*] Use `complex` instead of `int | float | complex`
|
35 | def f5(
36 | arg: Union[ # comment
@ -113,7 +112,7 @@ PYI041.pyi:36:10: PYI041 [*] Use `complex` instead of `int | float | complex`
40 38 |
41 39 | def f6(
PYI041.pyi:43:9: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:43:9: PYI041 [*] Use `complex` instead of `int | float | complex`
|
41 | def f6(
42 | arg: (
@ -136,7 +135,7 @@ PYI041.pyi:43:9: PYI041 [*] Use `complex` instead of `int | float | complex`
46 44 | )
47 45 | ) -> None: ... # PYI041
PYI041.pyi:49:26: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:49:26: PYI041 [*] Use `float` instead of `int | float`
|
47 | ) -> None: ... # PYI041
48 |
@ -155,7 +154,7 @@ PYI041.pyi:49:26: PYI041 [*] Use `float` instead of `int | float`
51 51 |
52 52 | def f6(arg1: int, *args: Union[Union[int, int, float]]) -> None: ... # PYI041
PYI041.pyi:52:26: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:52:26: PYI041 [*] Use `float` instead of `int | float`
|
52 | def f6(arg1: int, *args: Union[Union[int, int, float]]) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
@ -172,7 +171,7 @@ PYI041.pyi:52:26: PYI041 [*] Use `float` instead of `int | float`
54 54 |
55 55 | def f7(arg1: int, *args: Union[Union[Union[int, int, float]]]) -> None: ... # PYI041
PYI041.pyi:55:26: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:55:26: PYI041 [*] Use `float` instead of `int | float`
|
55 | def f7(arg1: int, *args: Union[Union[Union[int, int, float]]]) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
@ -189,7 +188,7 @@ PYI041.pyi:55:26: PYI041 [*] Use `float` instead of `int | float`
57 57 |
58 58 | def f8(arg1: int, *args: Union[Union[Union[int | int | float]]]) -> None: ... # PYI041
PYI041.pyi:58:26: PYI041 [*] Use `float` instead of `int | float`
PYI041_1.pyi:58:26: PYI041 [*] Use `float` instead of `int | float`
|
58 | def f8(arg1: int, *args: Union[Union[Union[int | int | float]]]) -> None: ... # PYI041
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
@ -206,7 +205,7 @@ PYI041.pyi:58:26: PYI041 [*] Use `float` instead of `int | float`
60 60 |
61 61 | class Foo:
PYI041.pyi:64:24: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:64:24: PYI041 [*] Use `complex` instead of `int | float | complex`
|
62 | def good(self, arg: int) -> None: ...
63 |
@ -227,7 +226,7 @@ PYI041.pyi:64:24: PYI041 [*] Use `complex` instead of `int | float | complex`
66 66 | def bad2(self, arg: int | Union[float, complex]) -> None: ... # PYI041
67 67 |
PYI041.pyi:66:25: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:66:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
64 | def bad(self, arg: int | float | complex) -> None: ... # PYI041
65 |
@ -248,7 +247,7 @@ PYI041.pyi:66:25: PYI041 [*] Use `complex` instead of `int | float | complex`
68 68 | def bad3(self, arg: Union[Union[float, complex], int]) -> None: ... # PYI041
69 69 |
PYI041.pyi:68:25: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:68:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
66 | def bad2(self, arg: int | Union[float, complex]) -> None: ... # PYI041
67 |
@ -269,7 +268,7 @@ PYI041.pyi:68:25: PYI041 [*] Use `complex` instead of `int | float | complex`
70 70 | def bad4(self, arg: Union[float | complex, int]) -> None: ... # PYI041
71 71 |
PYI041.pyi:70:25: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:70:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
68 | def bad3(self, arg: Union[Union[float, complex], int]) -> None: ... # PYI041
69 |
@ -288,8 +287,9 @@ PYI041.pyi:70:25: PYI041 [*] Use `complex` instead of `int | float | complex`
70 |+ def bad4(self, arg: complex) -> None: ... # PYI041
71 71 |
72 72 | def bad5(self, arg: int | (float | complex)) -> None: ... # PYI041
73 73 |
PYI041.pyi:72:25: PYI041 [*] Use `complex` instead of `int | float | complex`
PYI041_1.pyi:72:25: PYI041 [*] Use `complex` instead of `int | float | complex`
|
70 | def bad4(self, arg: Union[float | complex, int]) -> None: ... # PYI041
71 |
@ -304,3 +304,42 @@ PYI041.pyi:72:25: PYI041 [*] Use `complex` instead of `int | float | complex`
71 71 |
72 |- def bad5(self, arg: int | (float | complex)) -> None: ... # PYI041
72 |+ def bad5(self, arg: complex) -> None: ... # PYI041
73 73 |
74 74 |
75 75 | # https://github.com/astral-sh/ruff/issues/18298
PYI041_1.pyi:78:23: PYI041 [*] Use `float` instead of `int | float`
|
76 | # fix must not yield runtime `None | None | ...` (TypeError)
77 | class Issue18298:
78 | def f1(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
79 |
80 | def f3(self, arg: None | float | None | int | None = None) -> None: ... # PYI041 - with fix
|
= help: Remove redundant type
Safe fix
75 75 | # https://github.com/astral-sh/ruff/issues/18298
76 76 | # fix must not yield runtime `None | None | ...` (TypeError)
77 77 | class Issue18298:
78 |- def f1(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
78 |+ def f1(self, arg: None | None | float = None) -> None: ... # PYI041 - with fix
79 79 |
80 80 | def f3(self, arg: None | float | None | int | None = None) -> None: ... # PYI041 - with fix
PYI041_1.pyi:80:23: PYI041 [*] Use `float` instead of `int | float`
|
78 | def f1(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
79 |
80 | def f3(self, arg: None | float | None | int | None = None) -> None: ... # PYI041 - with fix
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
|
= help: Remove redundant type
Safe fix
77 77 | class Issue18298:
78 78 | def f1(self, arg: None | int | None | float = None) -> None: ... # PYI041 - with fix
79 79 |
80 |- def f3(self, arg: None | float | None | int | None = None) -> None: ... # PYI041 - with fix
80 |+ def f3(self, arg: None | float | None | None = None) -> None: ... # PYI041 - with fix

View file

@ -0,0 +1,12 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
---
PYI041_2.py:7:23: PYI041 Use `float` instead of `int | float`
|
5 | # fix must not yield runtime `None | None | ...` (TypeError)
6 | class Issue18298:
7 | def f1(self, arg: None | int | None | float = None) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
8 | pass
|
= help: Remove redundant type