Skip to content

PYI061 fix can change operator precedence #20265

@dscorbett

Description

@dscorbett

Summary

The fix for redundant-none-literal (PYI061) in Python 3.10 and later changes a subscription into a | expression, which has different precedence, which can change the program’s behavior outside of typing contexts. The fix should insert parentheses when necessary to maintain the correct precedence, i.e. (Literal[1] | None).__dict__ in this example:

$ cat >pyi061.py <<'# EOF'
from typing import Literal
print(Literal[1, None].__dict__)
# EOF

$ python pyi061.py
{'_inst': True, '_name': None, '__origin__': typing.Literal, '__slots__': None, '__args__': (1, None), '__parameters__': (), '__module__': 'typing'}

$ ruff --isolated check pyi061.py --select PYI061 --preview --target-version py310 --fix
Found 1 error (1 fixed, 0 remaining).

$ cat pyi061.py 
from typing import Literal
print(Literal[1] | None.__dict__)

$ python pyi061.py 2>&1 | tail -n 1
AttributeError: 'NoneType' object has no attribute '__dict__'. Did you mean: '__dir__'?

Version

ruff 0.12.12 (c6516e9 2025-09-04)

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixesRelated to suggested fixes for violations

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions