Incorrectly inferring generic function parameter type
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
Type: Bug
Hi. I'm using Python3.13. I have code that looks like this and works fine:
```python
from __future__ import annotations
from typing import Sequence, TypeIs, Callable
def f[B, A](a: Sequence[B | A], g: Callable[[B | A], TypeIs[A]]) -> tuple[B, A]:
...
def g(x: num | int) -> TypeIs[int]:
...
class num(int):
pass
l: list[num | int] = [num(1), 3]
h = f(l, g)
```
This works fine, but when I swap the `A` and `B` type variables, I get an error:
```python
from __future__ import annotations
from typing import Sequence, TypeIs, Callable
def f[A, B](a: Sequence[A | B], g: Callable[[A | B], TypeIs[B]]) -> tuple[A, B]:
...
def g(x: num | int) -> TypeIs[int]:
...
class num(int):
pass
l: list[num | int] = [num(1), 3]
h = f(l, g) # Error on g ... Pylance(reportArgumentType)
```
```
Argument of type "(x: num | int) -> TypeIs[int]" cannot be assigned to parameter "g" of type "(A@f | B@f) -> TypeIs[B@f]" in function "f"
Type "(x: num | int) -> TypeIs[int]" is not assignable to type "(int | num) -> TypeIs[num]"
Function return type "TypeIs[int]" is incompatible with type "TypeIs[num]"
"TypeIs[int]" is not assignable to "TypeIs[num]"
Type parameter "T@TypeIs" is invariant, but "int" is not the same as "num"
"bool" is not assignable to "TypeIs[num]"Pylance(reportArgumentType)
```
even though these are functionally the same.
Extension version: 2025.6.2
VS Code version: Code 1.102.0 (cb0c47c0cfaad0757385834bd89d410c78a856c0, 2025-07-09T22:10:34.600Z)
OS version: Windows_NT x64 10.0.19045
Modes:
System Added Logs
```
from __future__ import annotations
from typing import Sequence, TypeIs, Callable
def f[A, B](a: Sequence[A | B], g: Callable[[A | B], TypeIs[B]]) -> tuple[A, B]:
...
def g(x: num | int) -> TypeIs[int]:
...
class num(int):
pass
l: list[num | int] = [num(1), 3]
h = f(l, g) # Error ... Pylance(reportArgumentType)
```
System Info
|Item|Value|
|---|---|
|CPUs|AMD Ryzen 7 4800H with Radeon Graphics (16 x 2894)|
|GPU Status|2d_canvas: enabled
canvas_oop_rasterization: enabled_on
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
skia_graphite: disabled_off
video_decode: enabled
video_encode: enabled
vulkan: disabled_off
webgl: enabled
webgl2: enabled
webgpu: enabled
webnn: disabled_off|
|Load (avg)|undefined|
|Memory (System)|31.37GB (17.31GB free)|
|Process Argv|--crash-reporter-id 0a2c6f32-27fc-4931-a362-baccdd1378e2|
|Screen Reader|no|
|VM|0%|
A/B Experiments
```
vsliv368:30146709
vspor879:30202332
vspor708:30202333
vspor363:30204092
binariesv615:30325510
c4g48928:30535728
azure-dev_surveyone:30548225
962ge761:30959799
h48ei257:31000450
cppperfnew:31000557
dwnewjupytercf:31046870
nativeloc1:31344060
5fd0e150:31155592
dwcopilot:31170013
6074i472:31201624
dwoutputs:31242946
9064b325:31222308
copilot_t_ci:31333650
e5gg6876:31282496
pythoneinst12:31285622
c7cif404:31314491
pythonpulldiag:31343502
996jf627:31283433
pythonrdcb7:31342333
usemplatestapi:31297334
0aa6g176:31307128
747dc170:31275177
aj953862:31281341
generatesymbolt:31295002
convertfstringf:31295003
pylancequickfixt:31329274
9d2cg352:31346308
usemarketplace:31343026
nesew2to5:31336538
agentclaude:31335814
b6b4d950:31327385
nes-diff-11:31337487
nes-set-on:31340697
6abeh943:31336334
yijiwantestdri0626-c:31336931
64bie973:31346034
f76d9909:31342392
```
Contributor guide
Research direction
No source file or test is named; first reproduce the two generic-function examples in Pyright and compare the diagnostics when A and B are swapped. Done means the equivalent definitions produce consistent inference without the reported incompatible TypeIs error, with a regression test covering the case.
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
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100