Skip to content

False negative when using the power (**) operator #7765

Closed

Description

@nikola-benes

When checking the following function with mypy 0.730 (Python version 3.7.4):

def foo(x: int) -> str:
   return 2 ** x

mypy reports no errors:

Success: no issues found in 1 source file

With the --strict option turned on, mypy reports:

foo.py:2: error: Returning Any from function declared to return "str"

The expected output would be something like

foo.py:2: error: Incompatible return value type (got "int", expected "str")

Activity

  1. srittau commented on Oct 21, 2019

    @srittau
    Contributor

    This is an issue with typeshed due to a limitation in the type system. foo can return either an int or a float, depending on whether x is a positive or negative number. While we could change typeshed in a way that 2 ** x will always return float (which is correct, since for typing purposes int is a subtype if float), this would be rather annoying for users that know that it will return an int, for example because they know that x is always non-negative. Therefore we return Any, because there is no way to properly express this.

    We would need a range type to be able to express this.

  2. nikola-benes commented on Oct 21, 2019

    @nikola-benes
    Author

    Wouldn't Union[int, float] be a better option instead of Any? The users can then assert that the result is an int if they are sure that x is non-negative.

  3. nikola-benes commented on Oct 21, 2019

    @nikola-benes
    Author

    Also, a related problem is that

    def foo(x: int) -> float:
        return 2 ** x

    fails with mypy --strict. What is the recomended way to deal with this? Explicit type conversion (float(2 ** x))?

  4. msullivan commented on Oct 21, 2019

    @msullivan
    Collaborator

    Wouldn't Union[int, float] be a better option instead of Any? The users can then assert that the result is an int if they are sure that x is non-negative.

    We try to avoid that sort of union return in typeshed stubs because they produce a pretty bad user experience.

  5. msullivan commented on Oct 21, 2019

    @msullivan
    Collaborator

    Also, a related problem is that

    def foo(x: int) -> float:
        return 2 ** x

    fails with mypy --strict. What is the recomended way to deal with this? Explicit type conversion (float(2 ** x))?

    Yeah, probably. --disallow-return-any maybe shouldn't be in --strict? See #7767 which I just opened

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions