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

Scoping issue during if/elif? #12691

Closed
DamianZaremba opened this issue Apr 28, 2022 · 1 comment
Closed

Scoping issue during if/elif? #12691

DamianZaremba opened this issue Apr 28, 2022 · 1 comment
Labels
bug mypy got something wrong

Comments

@DamianZaremba
Copy link

Bug Report

When assigning to variables within an if elif block, mypy appears to incorrectly carry the assigned type between blocks (where it can never have been assigned in the else part).

To Reproduce

Using a very contrived example, which causes a common variable name to be "reused" between types;

x = 1
if x == 1:
    record = 1
elif x == 2:
    record = ""

mypy reports an incompatible type

$ mypy --strict test.py
test.py:5: error: Incompatible types in assignment (expression has type "str", variable has type "int")
Found 1 error in 1 file (checked 1 source file)

Expected Behavior

Since the second record variable cannot have been assigned (otherwise we would have never got to this block), it cannot have the type of int.

mypy should treat it as an unassigned variable and associate the new str type at the point of assignment.

Effectively this should result in no errors and be the same logically as e.g.

x = 1
if x == 1:
    record1 = 1
elif x == 2:
    record2 = ""

Which passes cleanly;

$ mypy --strict test.py 
Success: no issues found in 1 source file

Actual Behavior

mypy appears to be carrying the inferred type of the first assignment (in the if block) over into the second (elif block) assignment, even though the variable has not been assigned.

mypy view of the world;

test.py:8: note: Revealed type is "builtins.int"

python view of the world;

Traceback (most recent call last):
  File "/divesoft-parser/test.py", line 8, in <module>
    reveal_type(record)
NameError: name 'record' is not defined

Your Environment

  • Mypy version used:mypy 0.950 (compiled: yes)
  • Mypy command-line flags:--strict
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.9.12
  • Operating system and version: OSX 11.6.5

x-ref https://gitter.im/python/typing?at=626ac42846495f47cfb712a3

@DamianZaremba DamianZaremba added the bug mypy got something wrong label Apr 28, 2022
@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Apr 28, 2022

By default mypy only wants variables to be of a single type, see https://mypy.readthedocs.io/en/stable/common_issues.html#redefinitions-with-incompatible-types

This behaviour should work if you were to use --allow-redefinition, the relevant issue for that is #6232

Finally, in some cases, predeclaring the type of the variable can work, e.g.:

x = 1
record: object
if x == 1:
    record = 1
elif x == 2:
    record = ""

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

2 participants