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

Zero-long TypeVarTuple special case doesn't work #16199

Closed
TeamSpen210 opened this issue Sep 29, 2023 · 0 comments · Fixed by #16238
Closed

Zero-long TypeVarTuple special case doesn't work #16199

TeamSpen210 opened this issue Sep 29, 2023 · 0 comments · Fixed by #16238
Labels
bug mypy got something wrong topic-pep-646 PEP 646 (TypeVarTuple, Unpack)

Comments

@TeamSpen210
Copy link
Contributor

Bug Report

It seems the experimental variadic generic classes support doesn't handle having a zero-long tuple of types correctly. This is useful when handling a callback which takes no arguments. Both explicitly parametrizing with [()] and inferring from a function doesn't seem to work.

To Reproduce

from typing import Generic, Callable, TypeVarTuple, Unpack

T = TypeVarTuple("T")

def no_args() -> None: ...
def one_arg(a: int, /) -> None: ...

class MyClass(Generic[Unpack[T]]):
    func: Callable[[Unpack[T]], object]

    def __init__(self, func: Callable[[Unpack[T]], object]) -> None:
        self.func = func

def check(explicit: MyClass[()]) -> None:
    # note: Revealed type is "MyClass[Unpack[builtins.tuple[Any, ...]]]"
    reveal_type(explicit)
    # error: Incompatible types in assignment (expression has type "Callable[[], None]",
    # variable has type "Callable[[VarArg(Any)], object]")  [assignment]
    explicit.func = no_args
    implicit = MyClass(no_args)  # Inference doesn't work either.
    reveal_type(implicit)  # note: Revealed type is "MyClass"
    reveal_type(implicit.func) # note: Revealed type is "def (*Unpack[T`1]) -> builtins.object"
    implicit.func()  # error: Too few arguments  [call-arg]
    implicit.func(1)  # error: Argument 1 has incompatible type "int"; expected "Unpack[T]"  [arg-type]
    reveal_type(MyClass(one_arg))  # note: Revealed type is "MyClass[builtins.int]"

Expected Behavior

MyClass[()] should set T to be zero-long, thus accepting only functions with no args.

Actual Behavior

It looks like the TypeVarTuple is being set to tuple[Any, ...], which is not what is intended.

Your Environment

  • Mypy version used: master = 181cbe8
  • Mypy command-line flags: --new-type-inference --enable-incomplete-feature=Unpack --enable-incomplete-feature=TypeVarTuple
  • Python version used: 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)]
@TeamSpen210 TeamSpen210 added the bug mypy got something wrong label Sep 29, 2023
@ilevkivskyi ilevkivskyi added the topic-pep-646 PEP 646 (TypeVarTuple, Unpack) label Oct 5, 2023
ilevkivskyi added a commit that referenced this issue Oct 16, 2023
Fixes #16199

It was surprisingly hard to fix, because all possible fixes strongly
interfered with the code that makes "no-args" aliases possible:
```python
l = list
x: l[int]  # OK, same as list[int]
```
So after all I re-organized (and actually simplified) that old code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-pep-646 PEP 646 (TypeVarTuple, Unpack)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants