pylint-dev/pylint

possibly-used-before-assignment doesn't understand never-returning-functions

chrisburr opened this issue · 4 comments

Bug description

# pylint: disable=missing-module-docstring,invalid-name
import sys

if input("Enter something or nothing: "):
    sys.exit()
else:
    a = 1
print(a)

Configuration

No response

Command used

pylint test.py

Pylint output

************* Module test
test.py:8:6: E0606: Possibly using variable 'a' before assignment (possibly-used-before-assignment)

Expected behavior

Branches which end in a function which never returns shouldn't be considered as possible causes of never defined variables.

Pylint version

pylint 3.2.0
astroid 3.2.0
Python 3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:43:09) [GCC 12.3.0]

OS / Environment

No response

Additional dependencies

No response

I don't think is this a false positive. Variable a really is possibly undefined, in the sense that there are branches in which it is used but not defined. For example, if sys.exit is tampered with, a NameError can be raised:

import sys

sys.exit = lambda: None
if input("Enter something or nothing: "):
    sys.exit()
else:
    a = 1
print(a)

There is an easy way to silence this warning, namely to define a unconditionally:

import sys

if input("Enter something or nothing: "):
    sys.exit()

a = 1
print(a)

I think the proposal is to use the existing option never-returning-functions, which I think is a good idea and simple fix. The risk of tampering is almost nil, and it's under the user's control, if they want to test more rigorously they can supply an empty array to that setting.

Looks like never-returning-functions is documented as only dealing with one option, and there's already a TODO statement in the code to reuse it in pylint 4 for other purposes, so that's maybe better deferred.

In the meantime, we can solve the reporter's issue with using the existing util is_terminating_func.

Thanks a lot for the quick fix!