`TypeVar` with `Never` as an option and unexpected `reportArgumentType`
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Describe the bug**
Given `_Z = TypeVar('_Z', SomeType, Never)`, and `class SomeClass(Generic[_Z])`, you'd expect a function parameter of type `SomeClass[_Z]` would accept `SomeClass[Never]`. It does not.
**Code or Screenshots**
Code sample in [pyright playground](https://pyright-play.net/?code=GYJw9gtgBALgngBwJYDsDmUkQWEMoDiApikSEgMYA0UAckQG5k0AqiRAagIYgBQvAfQBaUALxQ2CTjwAUAcmFyaqGDXpMQASn4UANlwDOBqAGVIRAML6jM4qXIUA2sIC6mgFxQAdD94ATImAoA3MBYABXFAoZAU8zCEtrA2chNygAWgA%2BOjBSTx8vflQDGC4oogEVMVNzK0NklRcZbWLS8oFSDWr4xPrHdTIm7V4QhLDI6NayigqVTSgoAGIoMABrKBkUMBXwmARdmkMoIgAPKQoYIj9tUYqIqJkp9s6ybQX39%2BXI0-PLv2OQOAQABCKAIODkNAAC3wBi4cAM7l4Hw%2ByzIQM8AEEQGhwgkUPgwEF4FIoAAiHp1Iz9RiDMlQChlLb4ABGRCg9SQaFIfmRKIWyw%2BMG2CB4XASlxA5IE9KJsHY5MpSRSAAFbuMoi56ag%2BfzBe97hckLlyerDWTdSjlhTasqBiAtZhjMyOUYuSguCzdOzhYrbX1hGrQoatZbURIFaKQOKiJLpUIVUr6trjKgGDwkGVVFAWbtyfaU2HPiiXTAoey4QlXfGg2NzRsQEQcHhsbj8TBJERNEA)
```python
from typing import Generic, Never, TypeVar
_Z = TypeVar('_Z', int, Never)
class SomeClass(Generic[_Z]): ...
def some_func(_: SomeClass[_Z]) -> None: ...
instance_int = SomeClass[int]()
instance_never = SomeClass[Never]()
some_func(instance_int) # ok (no output, as expected)
some_func(instance_never)
# unexpected error! pyright says:
# error: Argument of type "SomeClass[Never]" cannot be assigned
# to parameter "_" of type "SomeClass[_Z@some_func]" in
# function "some_func"
# "SomeClass[Never]" is not assignable to "SomeClass[_Z@some_func]"
# Type parameter "_Z@SomeClass" is invariant, but "Never" is
# not the same as "_Z@some_func" (reportArgumentType)
```
**If this is intended behavior...**
What's the best workaround for a class which may or may not have (for example) a special-case placeholder value?
```python
class SomeClass(Generic[_Z]):
def foo_to_bar(self, value: float) -> int | _Z: ...
def bar_to_foo(self, value: int | _Z) -> float: ...
```
Concrete example: a monotonic mapping from non-negative floats to another linear float space might be the identity function (`lambda x: x`) or might be `log()`/`exp()` with a special case for zero.
**VS Code extension or command-line**
Tested with latest (1.1.414) on pyright-play.net, and via LSP.
Contributor guide
Research direction
Start by running the linked pyright playground sample with version 1.1.414, then reproduce it through the LSP as reported. Trace how the checker handles the constrained TypeVar with Never when checking SomeClass[Never] against some_func, and consider the issue resolved when that call no longer produces reportArgumentType while the existing SomeClass[int] behavior remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100