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

MyPy doesn't take into account default parameters when restricting typevars #16386

Closed
andrewjw opened this issue Nov 1, 2023 · 4 comments
Closed
Labels
bug mypy got something wrong

Comments

@andrewjw
Copy link

andrewjw commented Nov 1, 2023

Bug Report

If you have a function that uses a TypeVar to fix the type of multiple parameters, and one of those has a default value that restricts the possible types, MyPy doesn't raise an error if a caller uses the default parameter but has an invalid type in the other.

To Reproduce

from typing import Any, Callable, List, TypeVar

T = TypeVar("T", bound=Any)

def default_map(x: int) -> int:
    return x

def sum_values(values: List[T], map_func: Callable[[T], int] = default_map) -> int:
    return sum([map_func(x) for x in values])

sum_values(["abc", "defg"], map_func=len)

sum_values(["abc", "defg"])

Playground: https://mypy-play.net/?mypy=latest&python=3.12&gist=6733a6d4078776cb4c54bfca985c3dc5

Expected Behavior

MyPy should report an error for the second call to sum_values as str is not a valid type for T when the default map restricts it to int.

Actual Behavior

No error reported by MyPy, but a runtime error in Python.

Traceback (most recent call last):
  File "/Users/a.wilkinson1/Downloads/mypy_map_func_error.py", line 13, in <module>
    sum_values(["abc", "defg"])
  File "/Users/a.wilkinson1/Downloads/mypy_map_func_error.py", line 9, in sum_values
    return sum([map_func(x) for x in values])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Your Environment

  • Mypy version used: 1.6.1
  • Python version used: 3.11 and 3.12
@andrewjw andrewjw added the bug mypy got something wrong label Nov 1, 2023
@andrewjw
Copy link
Author

andrewjw commented Nov 1, 2023

I should add, if you include the default parameter when calling the function you get the correct error from MyPy.

sum_values(["abc", "defg"], default_map)

mypy_map_func_error.py:14: error: Argument 2 to "sum_values" has incompatible type "Callable[[int], int]"; expected "Callable[[str], int]"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

@ilevkivskyi
Copy link
Member

You should remove that bound=Any on the type variable (Any is not the same as object). Having such type variable is almost the same as having plain Any. Mypy will then give an error, likely not in a place where you want, but then it is #3737

@ilevkivskyi ilevkivskyi closed this as not planned Won't fix, can't repro, duplicate, stale Nov 1, 2023
@andrewjw
Copy link
Author

andrewjw commented Nov 2, 2023

Fair point about bound, that's definitely my mistake.

Without that you get the error error: Incompatible default for argument "map_func" (default has type "Callable[[int], int]", argument has type "Callable[[T], int]") [assignment]. I'd argue that this is incorrect, as the default value is compatible. It's more specific than the type of the argument, but it's definitely compatible. I'm not sure how I'd create a default value that was compatible, given the typevar in the type.

@ilevkivskyi
Copy link
Member

ilevkivskyi commented Nov 2, 2023

This is what issue #3737 is about.

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

No branches or pull requests

2 participants