Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False positive from used-before-assignment when variable is reimported #7882

Closed
MarcoGorelli opened this issue Dec 1, 2022 · 3 comments · Fixed by #8095
Closed

False positive from used-before-assignment when variable is reimported #7882

MarcoGorelli opened this issue Dec 1, 2022 · 3 comments · Fixed by #8095
Labels
C: used-before-assignment Issues related to 'used-before-assignment' check False Positive 🦟 A message is emitted but nothing is wrong with the code Good first issue Friendly and approachable by new contributors Needs PR This issue is accepted, sufficiently specified and now needs an implementation
Milestone

Comments

@MarcoGorelli
Copy link
Contributor

MarcoGorelli commented Dec 1, 2022

Bug description

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from foo import Bar

def myfunc():
    result: Bar

    from foo import Bar # if I remove this, then no error is reported

Note how if I remove the from foo import Bar line, then the error goes away

Command used

pylint --disable=all --enable=used-before-assignment t.py

Pylint output

************* Module t
t.py:7:12: E0601: Using variable 'Bar' before assignment (used-before-assignment)

------------------------------------------------------------------
Your code has been rated at 1.67/10 (previous run: 1.67/10, +0.00)

Expected behavior

No error reported

Pylint version

pylint 2.15.7
astroid 2.12.13
Python 3.8.15 (default, Oct 12 2022, 19:15:16) 
[GCC 11.2.0]
@MarcoGorelli MarcoGorelli added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Dec 1, 2022
@Pierre-Sassoulas Pierre-Sassoulas added False Positive 🦟 A message is emitted but nothing is wrong with the code Needs PR This issue is accepted, sufficiently specified and now needs an implementation and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Dec 1, 2022
@jacobtylerwalls jacobtylerwalls added the C: used-before-assignment Issues related to 'used-before-assignment' check label Dec 1, 2022
@orSolocate
Copy link
Contributor

Maybe it is an astroid issue and not Pylint?
Would be interesting to debug the infer used on Bar during used-before-assignment check..

@mbyrnepr2
Copy link
Member

Thanks for the report.

I think Pylint is struggling with this:

if TYPE_CHECKING:
    from foo import Bar

Replacing with the following makes the false positive go away:

from foo import Bar

@jacobtylerwalls
Copy link
Member

jacobtylerwalls commented Jan 16, 2023

Very similar to #7609, we need to account for the fact that annotations are not evaluated at runtime in the body of a function.

This appears to work:

diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 0d72ef969..486137ada 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -1799,17 +1799,20 @@ class VariablesChecker(BaseChecker):
                 # E0601 may *not* occurs in lambda scope.
 
                 # Handle postponed evaluation of annotations
-                if not (
-                    self._postponed_evaluation_enabled
-                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
+                if self._postponed_evaluation_enabled and isinstance(stmt, nodes.FunctionDef):
+                    return (VariableVisitConsumerAction.CONTINUE, [node])
+                # Handle unevaluated annotation inside the body of a function)
+                if (
+                    isinstance(stmt, nodes.AnnAssign)
+                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
                 ):
-                    self.add_message(
-                        "used-before-assignment",
-                        args=node.name,
-                        node=node,
-                        confidence=HIGH,
-                    )
-                    return (VariableVisitConsumerAction.RETURN, found_nodes)
+                    return (VariableVisitConsumerAction.CONTINUE, [node])
+                self.add_message(
+                    "used-before-assignment",
+                    args=node.name,
+                    node=node,
+                    confidence=HIGH,
+                )
 
             elif base_scope_type == "lambda":
                 # E0601 can occur in class-level scope in lambdas, as in

@jacobtylerwalls jacobtylerwalls added the Good first issue Friendly and approachable by new contributors label Jan 16, 2023
@jacobtylerwalls jacobtylerwalls added this to the 2.16.1 milestone Jan 16, 2023
@jacobtylerwalls jacobtylerwalls removed this from the 2.16.1 milestone Jan 22, 2023
@Pierre-Sassoulas Pierre-Sassoulas added this to the 2.16.0 milestone Jan 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: used-before-assignment Issues related to 'used-before-assignment' check False Positive 🦟 A message is emitted but nothing is wrong with the code Good first issue Friendly and approachable by new contributors Needs PR This issue is accepted, sufficiently specified and now needs an implementation
Projects
None yet
5 participants