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

Flag None check on value that cannot be None #18386

Open
nickdrozd opened this issue Dec 30, 2024 · 4 comments
Open

Flag None check on value that cannot be None #18386

nickdrozd opened this issue Dec 30, 2024 · 4 comments
Labels

Comments

@nickdrozd
Copy link
Contributor

Say I have function that maybe returns None and I check the result:

def f() -> int | None: ...

if f() is None: ...

I rewrite the function so that it never returns None:

def f() -> int: ...

if f() is None: ...

Now the is None check makes no sense -- it will always fail. This is a mistake introduced in refactoring and it should be flagged. (And similar for is not None checks)

In Rust I don't think this kind of error is possible:

fn f() -> Option<u8>;

if f().is_none() {}  // okay

fn g() -> u8;

if g().is_none() {} // no good
@A5rocks
Copy link
Contributor

A5rocks commented Jan 1, 2025

Both --warn-unreachable and --strict-equality should work for this. But they don't! That's a bug.

Maybe worth closing this to make a bug report? Or someone can change tags (I can't :'( ).

@nickdrozd
Copy link
Contributor Author

Forgot to add, this affects Mypy 1.14.1 with Python 3.14, using --strict setting. (Not sure if --warn-unreachable is included in that, but if it isn't it should be.)

Switching the tag from feature to bug is fine with me :)

@A5rocks
Copy link
Contributor

A5rocks commented Jan 1, 2025

It isn't included in that. Maybe thumbs up #18078!

@nickdrozd
Copy link
Contributor Author

Here is a full example:

from random import randrange

def f(x: int) -> int | None:
    return None if x == 0 else 2 * x

def g(x: int) -> int:
    return 2 * x

if __name__ == '__main__':
    if f(randrange(10)) is None:
        print('f: got 0')

    if g(randrange(10)) is None:  # <-- unreachable but not flagged
        print('g: got 0')

mypy --strict --warn-unreachable does not raise any warnings, but it should. So this is a FALSE NEGATIVE bug. Or a new feature, whatever, but in any case this situation should be flagged.

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

No branches or pull requests

2 participants