mypy icon indicating copy to clipboard operation
mypy copied to clipboard

possibly-undefined false negative for variable annotation

Open hauntsaninja opened this issue 1 year ago • 1 comments

Reported by KotlinIsland in #16609

# mypy: enable-error-code="possibly-undefined"

def foo() -> None:
    a: int
    print(a)

https://mypy-play.net/?mypy=latest&python=3.12&gist=a044519fd87d51e6028a236f02bcb9cb

hauntsaninja avatar Jun 13 '24 03:06 hauntsaninja

I think a distinction between "definition" and "binding" should be made. pyright refers to this as reportUnboundVariable, and this mirrors the runtime exception you would receive:

# pyright / mypy / runtime
def f():
    a: int
    print(a)  # reportUnboundVariable / <nothing> / UnboundLocalError

    print(b)  # reportUndefinedVariable / name-defined / NameError

KotlinIsland avatar Jun 13 '24 04:06 KotlinIsland

I think the discussed problem is not a limitation of possibly-undefined, because If you use --enable-error-code possibly-undefined, mypy generates an error if it cannot verify that a variable will be defined in all execution paths. In the discussed example, a is clearly not defined (or not bound). Such errors should be reported with the name-defined error code (or, eventually, a new name-unbound error code).

Mypy searches for name-defined errors during the semantic analysis step and does the possibly-defined analysis at the end of type checking. The possibly-defined analysis thereby ensures that it does not re-report errors already reported during semantic analysis.

I experimented with extending only the semantic analysis part, but did not open a PR far because I was a little shocked that it caused thousands of tests to fail. But I was only shocked because I had got used to the habit of writing test cases with unbound names:

class C:
    x: int
c: C
reveal_type(c.x)  # int

So, adding a name-unbound error code (or something similar), as suggested by @KotlinIsland, would be highly practical for this and similar cases, as it would allow turning the new checks off while keeping the old name-defined checks activated.

tyralla avatar Nov 03 '25 21:11 tyralla

a is clearly not defined

it's clearly defined as int. perhaps this is an issue with semantics

KotlinIsland avatar Nov 04 '25 01:11 KotlinIsland

a is clearly not defined

it's clearly defined as int. perhaps this is an issue with semantics

I agree. I just wanted to say that, if the reported problem is a bug, it is a deficit of name-defined and not of possibly-undefined. If we interpret this issue as a feature request, then we are IMO talking about the two new error codes name-unbound (enabled by default?) and possibly-unbound (optional). And, before experimenting, I was unsure whether adding two new error codes instead of just subsuming definition errors and unbound errors under name-defined (and possibly-defined) is worth it.

tyralla avatar Nov 04 '25 06:11 tyralla