diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP007.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP007.py index 5f23a92af2e8b..af1c1ca35b3a4 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP007.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP007.py @@ -114,3 +114,8 @@ class ServiceRefOrValue: class Collection(Protocol[*_B0]): def __iter__(self) -> Iterator[Union[*_B0]]: ... + + +# Regression test for: https://github.com/astral-sh/ruff/issues/8609 +def f(x: Union[int, str, bytes]) -> None: + ... diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs index 73f1075140402..1823e116d7fec 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -147,10 +147,10 @@ fn union(elts: &[Expr]) -> Expr { }), [Expr::Tuple(ast::ExprTuple { elts, .. })] => union(elts), [elt] => elt.clone(), - [elt, rest @ ..] => Expr::BinOp(ast::ExprBinOp { - left: Box::new(union(&[elt.clone()])), + [rest @ .., elt] => Expr::BinOp(ast::ExprBinOp { + left: Box::new(union(rest)), op: Operator::BitOr, - right: Box::new(union(rest)), + right: Box::new(union(&[elt.clone()])), range: TextRange::default(), }), } diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP007.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP007.py.snap index 4c8f7cc2c9b58..77252939a755b 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP007.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP007.py.snap @@ -50,7 +50,7 @@ UP007.py:14:10: UP007 [*] Use `X | Y` for type annotations 12 12 | 13 13 | 14 |-def f(x: Union[str, int, Union[float, bytes]]) -> None: - 14 |+def f(x: str | (int | Union[float, bytes])) -> None: + 14 |+def f(x: str | int | Union[float, bytes]) -> None: 15 15 | ... 16 16 | 17 17 | @@ -176,7 +176,7 @@ UP007.py:38:11: UP007 [*] Use `X | Y` for type annotations 36 36 | 37 37 | 38 |-def f(x: "Union[str, int, Union[float, bytes]]") -> None: - 38 |+def f(x: "str | (int | Union[float, bytes])") -> None: + 38 |+def f(x: "str | int | Union[float, bytes]") -> None: 39 39 | ... 40 40 | 41 41 | @@ -414,4 +414,21 @@ UP007.py:110:28: UP007 [*] Use `X | Y` for type annotations 112 112 | 113 113 | # Regression test for: https://github.com/astral-sh/ruff/issues/7452 +UP007.py:120:10: UP007 [*] Use `X | Y` for type annotations + | +119 | # Regression test for: https://github.com/astral-sh/ruff/issues/8609 +120 | def f(x: Union[int, str, bytes]) -> None: + | ^^^^^^^^^^^^^^^^^^^^^^ UP007 +121 | ... + | + = help: Convert to `X | Y` + +ℹ Unsafe fix +117 117 | +118 118 | +119 119 | # Regression test for: https://github.com/astral-sh/ruff/issues/8609 +120 |-def f(x: Union[int, str, bytes]) -> None: + 120 |+def f(x: int | str | bytes) -> None: +121 121 | ... +