Tobias Hermann
Tobias Hermann

Reputation: 10926

Detecting type errors using mypy without type annotations

The following script contains an intentional type error:

def foo(x, y):
    print(x[:y])

def main():
    foo('abcde', '2')

if __name__ == "__main__":
    main()

The error can be confirmed by running it:

$ python3 untyped_test.py 
Traceback (most recent call last):
  File "untyped_test.py", line 8, in <module>
    main()
  File "untyped_test.py", line 5, in main
    foo('abcde', '2')
  File "untyped_test.py", line 2, in foo
    print(x[:y])
TypeError: slice indices must be integers or None or have an __index__ method

However I was hoping to catch something like this not only at runtime but before executing the code using:

mypy --check-untyped-defs untyped_test.py 

But it does not find any errors:

$ mypy --check-untyped-defs untyped_test.py 
$ mypy --version
mypy 0.590

Only when I annotate foo:

def foo(x: str, y: int):
    print(x[:y])

I get:

untyped_test.py:5: error: Argument 2 to "foo" has incompatible type "str"; expected "int"

Is it possible to find errors like this without any manual type annotations?

Upvotes: 4

Views: 1037

Answers (1)

Michael0x2a
Michael0x2a

Reputation: 63978

This is not possible to do in mypy. Mypy follows PEP 484 semantics, which states that if a function's parameters are unannotated, they are assumed to have a type of Any, which represents a fully dynamic value of unknown type.

This design decision is intentional. This is in part because doing whole-program type inference is challenging, especially once you permit objects, subtyping, mutability, and so forth: asking the user to fix types at the "boundary" helps make type hinting tractable.

This is also in part to help ensure backwards compatibility. Type hints were intentionally designed such that it's possible to mix untyped and dynamic code with typed code in a meaningful way. This is particularly useful if you want to introduce type hinting to an existing project: everything, by default, is guaranteed to be considered dynamically typed, which lets you slowly add in types without being overwhelmed with errors. (That's the dream, at least -- I don't think mypy doesn't quite let you do this.)

That said, there are some people who are attempting to implement whole-program type inference -- see the pytype project, for example. However, my understanding is that it's still very much in alpha stage.

Upvotes: 1

Related Questions