Skip to content

Detect impossible condition caused by user defined __bool__ #7008

Closed

Description

@graingert

Eg with the following:

from typing import *

class Foo:
    def __bool__(self) -> Literal[True]:
        return True

def some_foo() -> Foo:
    ...

def throw_error():
    raise Exception


if __name__ == '__main__':
    print(some_foo() or throw_error())
    #                   ^^^^^^^^^^^^^  impossible condition, unreachable

mypy should be able to detect that the call to throw_error is unreachable

Activity

  1. ilevkivskyi commented on Jun 17, 2019

    @ilevkivskyi
    Member

    Well mypy doesn't detect even simpler unreachable function calls like True or print(). It may be a useful feature to warn about unreachable code.

    Related to #2395

  2. ilevkivskyi commented on Jun 17, 2019

    @ilevkivskyi
    Member

    #6990 is another example where this may be useful.

  3. Michael0x2a commented on Jun 17, 2019

    @Michael0x2a
    Collaborator

    FWIW I've started sort of looking into adding in some kind of flag for this during the past week (I'm already poking around this corner of the codebase for literal and enum reachability stuff anyways).

    I think in principle it should be straightforward: to avoid false-positives with things like sys.platform checks, we don't alert on blocks that were marked as unreachable as a part of semantic analysis and only look at results from the type-checking phase.

    We'll also probably want to adjust mypy so it distinguishes between intentionally and unintentionally unreachable blocks. E.g. if somebody does if False: ... that was probably intentional so we'll probably need to do something different there. Probably we'll need to refactor find_isinstance_check a bit to make this all work cleanly, but I was maybe thinking of doing that anyways.

    TBH I think the hardest/most annoying part will be constructing an understandable error message for subexpressions that were skipped due to being unreachable, just due to the "line-by-line" nature of error reporting in mypy.

    Possibly adding in a "fyi this expression is always True/always False" error message might be sufficient instead, as opposed to indicating specific ignored subexpressions. Not sure, still need to do more poking around.

  4. ilevkivskyi commented on Jun 19, 2019

    @ilevkivskyi
    Member

    TBH I think the hardest/most annoying part will be constructing an understandable error message for subexpressions that were skipped due to being unreachable, just due to the "line-by-line" nature of error reporting in mypy.

    On Python 3.8 there is a simple solution for that: ast.get_source_segment() gives exact source code for every AST node. But maybe a more generic error message would be sufficient.

    E.g. if somebody does if False: ... that was probably intentional

    On the other hand adding a # type: ignore to that code of switching it to if typing.TYPE_CHECKING: ... is probably a fine solution too.

  5. graingert commented on Jun 19, 2019

    @graingert
    ContributorAuthor
  6. ilevkivskyi commented on Sep 5, 2019

    @ilevkivskyi
    Member

    It looks like #7454 will help with this. @Michael0x2a is there something else apart from better error location needed for this issue? If not, I would propose to close this one.

  7. ilevkivskyi commented on Sep 5, 2019

    @ilevkivskyi
    Member

    Actually I think -> Literal[True] (currently not supported by --warn-unreachable) part is enough to keep this open.

  8. intgr commented on Mar 21, 2023

    @intgr
    Contributor

    FWIW mypy is now capable of warning on ilevkivskyi's case with --warn-unreachable (Playground link)

    from typing import *
    
    def some_foo() -> Literal[True]:
        return True
    
    def throw_error():
        raise Exception
    
    if __name__ == '__main__':
        print(some_foo() or throw_error())
        #                   ^^^^^^^^^^^^^ error: Right operand of "or" is never evaluated  [unreachable]

    It doesn't handle def __bool__(self) -> Literal[True] for objects.

    Should we close this or keep it open for extra __bool__ handling?

  9. ilevkivskyi commented on Mar 27, 2023

    @ilevkivskyi
    Member

    Yeah, let's keep this open for __bool__ support.

  10. changed the title [-]detect impossible condition[/-] [+]Detect impossible condition caused by user defined __bool__[/+] on Mar 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions