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

Difference in behaviour between overload and TypeVars when using functools.update_wrapper #17196

Open
hajarmitage opened this issue Apr 30, 2024 · 3 comments
Labels
bug mypy got something wrong

Comments

@hajarmitage
Copy link

Bug Report

When calling functools.update_wrapper(f, g) where f has a type of TypeVar('T', Type1, Type2), mypy errors incorrectly, saying it expects Callable[[Never], Never] in that spot.

To Reproduce
https://mypy-play.net/?mypy=latest&python=3.12&gist=8b79db2fe7eb042e15122536a393dd43

Expected Behavior

I think f1 and f2 are identical functions. I expect both checks to succeed (as they did on mypy 1.9.0), or possibly both to fail (but if this is an error, I don't see why...).

Actual Behavior

update_wrapper(f1, g) succeeds and update_wrapper(f2, g) errors, with the message Argument 1 to "update_wrapper" has incompatible type "Callable[[T], T]"; expected "Callable[[Never], Never]" [arg-type]

Your Environment

  • Mypy version used: 1.9.0 -> 1.10.0
  • Python version used: 3.10, 3.12
@hajarmitage hajarmitage added the bug mypy got something wrong label Apr 30, 2024
@burrowsa
Copy link

I also see this issue. Is there a fix or work around?

@hauntsaninja
Copy link
Collaborator

If you want a workaround, you could use TypeVar(..., bound=int | str) (in general I think value constrained TypeVars are weird and get used in places when a bound is better)

@wcorrea-ec
Copy link

I'm not sure, but I think the new mypy is correct.

A variable of type T may be a str or an int. So f2's signature is equivalent to def f2(x: str | int) -> str | int. I could pass either type and I could get either type in return, not necessarily the one I passed in. That's incompatible with g, which only accepts and returns int.

Also, I think the type annotation for f1 is incorrect. If you ask mypy to reveal the type, you'll see: "Overload(def (x: builtins.str) -> builtins.str, def (x: builtins.int) -> builtins.int)". So the type of f1 is Callable[[str], str] | Callable[[int], int], not Callable[[str|int], [str|int]], which is the type of f2.

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

4 participants