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 negative involving null checks on optional types #5423

Open
person594 opened this issue Aug 6, 2018 · 6 comments · May be fixed by #18180
Open

False negative involving null checks on optional types #5423

person594 opened this issue Aug 6, 2018 · 6 comments · May be fixed by #18180
Labels
bug mypy got something wrong priority-0-high topic-reachability Detecting unreachable code topic-runtime-semantics mypy doesn't model runtime semantics correctly topic-type-narrowing Conditional type narrowing / binder

Comments

@person594
Copy link

Here is a minimal program demonstrating the problem:

foo = None
for _ in range(2):
  if foo is not None:
    print(1[2])
  foo = 1

Expected behavior:
error: Value of type "int" is not indexable

Actual behavior:
mypy accepts the program as valid, when run with the --strict flag

This issue seems to be a problem with how mypy handles reassignment to None type variables, and static evaluation of conditionals. After line 1, foo has the type None according to mypy. Thus, mypy determines that the condition on line 3 will never hold, and thus doesn't do type checking for the body of the if statement. On line 5, foo's type changes to Optional[int]. This, however, will only be reflected in code that follows line 5.

@ilevkivskyi
Copy link
Member

Hm, indeed, the conditional binder still doesn't catch all the corner cases. But actually by preference would be to just show errors in unreachable code in the strict mode.

@msullivan
Copy link
Collaborator

This bug is actually pretty bad, I think. It comes up not infrequently and has a pretty bad knock-on effect on mypyc, where it causes bizarre type errors of the form TypeError: None object expected

@ilevkivskyi
Copy link
Member

@msullivan
I left a comment in a very similar issue (a duplicate?) recently #7204 (comment). That "proposal" didn't get much traction however (although it seems to me the binder refactoring might me of smaller size than the semantic analyzer one, plus it can be split into few parts).

@JukkaL
Copy link
Collaborator

JukkaL commented Aug 12, 2019

This might be easy to fix without a major refactoring. Maybe we only need to modify how is None / is not None checks behave when the type is a partial type.

@msullivan
Copy link
Collaborator

Hm, there are cases where this breaks mypyc without is None checks:

def foo() -> None:
    last = None
    for i in range(10):
        print(last)
        last = i

msullivan added a commit that referenced this issue Sep 7, 2019
Currently when we encounter #5423 (when someting is incorrectly
inferred as None), we generate code that casts a variable to None
incorrectly since we are confused about the real type.

Now produce an error message saying to add an annotation when we
detect it.

Fix up the places in mypy this caused errors.
msullivan added a commit that referenced this issue Sep 7, 2019
Currently when we encounter #5423 (when someting is incorrectly
inferred as None), we generate code that casts a variable to None
incorrectly since we are confused about the real type.

Now produce an error message saying to add an annotation when we
detect it.

Fix up the places in mypy this caused errors.
msullivan added a commit that referenced this issue Sep 9, 2019
Currently when we encounter #5423 (when someting is incorrectly
inferred as None), we generate code that casts a variable to None
incorrectly since we are confused about the real type.

Now produce an error message saying to add an annotation when we
detect it.

Fix up the places in mypy this caused errors.
rjcohn pushed a commit to rjcohn/environs that referenced this issue Feb 4, 2021
If a default includes a reference to a variable, expand that reference.
See test_environs.test_default_expands.
Note: type for subs_default is required because of a bug in mypy:
  python/mypy#5423
sloria added a commit to sloria/environs that referenced this issue Feb 7, 2021
* Apply variable expansion to default values

If a default includes a reference to a variable, expand that reference.
See test_environs.test_default_expands.
Note: type for subs_default is required because of a bug in mypy:
  python/mypy#5423

* Update CHANGELOG

Co-authored-by: Richard Cohn <[email protected]>
Co-authored-by: Steven Loria <[email protected]>
@AlexWaygood AlexWaygood added topic-reachability Detecting unreachable code topic-runtime-semantics mypy doesn't model runtime semantics correctly labels Apr 3, 2022
@joshinils
Copy link

joshinils commented Aug 28, 2022

in case anyone comes here for help:
i annotated a variable used in a loop under an if-statement with foo: Optional[float] = None where it previously was not.
after that the error went away.
I guess mypy assumed the type to be NoneType or something and that it could never be float.

(lesson for me here is; always try to annotate more, it'll not only help me but also mypy)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong priority-0-high topic-reachability Detecting unreachable code topic-runtime-semantics mypy doesn't model runtime semantics correctly topic-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants