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

Incorrect mypy behavor when "type unpacking". #15997

Closed
gresm opened this issue Aug 30, 2023 · 6 comments
Closed

Incorrect mypy behavor when "type unpacking". #15997

gresm opened this issue Aug 30, 2023 · 6 comments
Labels
bug mypy got something wrong

Comments

@gresm
Copy link
Contributor

gresm commented Aug 30, 2023

Bug Report
When running provided script, mypy incorrectly flags it as Syntax error in type annotation even though it works perfectly fine in the interpreter.

To Reproduce
https://gist.github.com/mypy-play/6d44ea039080875ea31e83c4479fd7da
https://mypy-play.net/?mypy=master&python=3.10&gist=6d44ea039080875ea31e83c4479fd7da

Expected Behavior
Should work like in interpreter:

>>> CallableOrString: TypeAlias = Union[Callable[[T], T2], str]
>>> CallableOrString
typing.Union[typing.Callable[[~T], ~T2], str]
>>> CallableOrString[(int, int), str]
typing.Union[typing.Callable[[int, int], str], str]
>>> 
>>> 
>>> # Note this weird error when used list, not tuple.
>>> CallableOrString[[int, int], str]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.10/typing.py", line 312, in inner
    return func(*args, **kwds)
  File "/usr/lib/python3.10/typing.py", line 1081, in __getitem__
    return self.copy_with(tuple(new_args))
  File "/usr/lib/python3.10/typing.py", line 1240, in copy_with
    return Union[params]
  File "/usr/lib/python3.10/typing.py", line 312, in inner
    return func(*args, **kwds)
  File "/usr/lib/python3.10/typing.py", line 403, in __getitem__
    return self._getitem(self, parameters)
  File "/usr/lib/python3.10/typing.py", line 516, in Union
    parameters = _remove_dups_flatten(parameters)
  File "/usr/lib/python3.10/typing.py", line 281, in _remove_dups_flatten
    return tuple(_deduplicate(params))
  File "/usr/lib/python3.10/typing.py", line 255, in _deduplicate
    all_params = set(params)
  File "/usr/lib/python3.10/typing.py", line 1038, in __hash__
    return hash((self.__origin__, self.__args__))
TypeError: unhashable type: 'list'

Mypy should resolve CallableOrString[(int, int), str] to typing.Union[typing.Callable[[int, int], str], str].

Actual Behavior

<string>:8: error: Syntax error in type annotation  [syntax]
<string>:8: note: Suggestion: Use Tuple[T1, ..., Tn] instead of (T1, ..., Tn)
<string>:11: error: Too many arguments  [call-arg]
Found 2 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: latest (master branch), latest stable release (1.5.1)
  • Mypy command-line flags: mypy file.py or mypy -c [code]
  • Mypy configuration options from mypy.ini (and other config files): [none]
  • Python version used: 3.10.12
@gresm gresm added the bug mypy got something wrong label Aug 30, 2023
@gresm
Copy link
Contributor Author

gresm commented Aug 30, 2023

Might be related to #13337.

@erictraut
Copy link

erictraut commented Aug 30, 2023

The code in this sample contains a bug. The type variable T should be a ParamSpec rather than a TypeVar. For information about how to use ParamSpec, refer to PEP 612.

Here's the corrected code, which type checks without error in mypy:

from typing import ParamSpec, TypeVar, TypeAlias, Callable

P = ParamSpec("P")
T2 = TypeVar("T2")
CallableOrString: TypeAlias = Callable[P, T2] | str

def test(var: CallableOrString[[int, int], str]):
    if isinstance(var, str):
        return var
    return var(1, 2)

@gresm
Copy link
Contributor Author

gresm commented Aug 30, 2023

Hey @erictraut Indeed, this is an error on my part, but the error was unhelpful, would it be possible to improve it? And also it is weird that CallableOrString[(int, int), str] works on runtime, but not with mypy. Thanks for pointing out this fact, but your code actually raises quite a few mypy errors 😅

<string>:3: error: ParamSpec() expects a string literal as first argument  [misc]
<string>:3: error: Cannot determine type of "P"  [has-type]
<string>:4: error: TypeVar() expects a string literal as first argument  [misc]
<string>:4: error: Cannot determine type of "T2"  [has-type]
<string>:5: error: The first argument to Callable must be a list of types, parameter specification, or "..."  [valid-type]
<string>:5: note: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas
<string>:7: error: Bracketed expression "[...]" is not valid as a type  [valid-type]
<string>:7: note: Did you mean "List[...]"?
<string>:7: error: Bad number of arguments for type alias, expected: 0, given: 2  [type-arg]
Found 7 errors in 1 file (checked 1 source file)

Again, your code works correctly on runtime and TypeAlias is correctly resolved there, but it doesn't work with mypy.

@gresm
Copy link
Contributor Author

gresm commented Aug 30, 2023

My bad, your code works. I just was running it improperly.

@JelleZijlstra
Copy link
Member

Mypy is behaving as expected here. The one area for improvement is that we could perhaps improve the error message, maybe to something like "tuple not supported here". If someone wants to pick that up, feel free to open a PR, but closing this issue as the type checker behavior is correct.

@JelleZijlstra JelleZijlstra closed this as not planned Won't fix, can't repro, duplicate, stale Aug 30, 2023
@gresm
Copy link
Contributor Author

gresm commented Aug 30, 2023

I actually also had another problem with this, but it turned out that it was #13337 (which still is an issue for me).

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

3 participants