Commit 94109aa
authored
Fix TypeVar upper bounds sometimes not being displayed in pretty callables (#17802)
Fixes #17792. Related to #17791.
Currently,
[`pretty_callable`](https://github.com/python/mypy/blob/5dfc7d941253553ab77836e9845cb8fdfb9d23a9/mypy/messages.py#L2862)
only renders `TypeVar` upper bounds if they are of type `Instance`:
https://github.com/python/mypy/blob/5dfc7d941253553ab77836e9845cb8fdfb9d23a9/mypy/messages.py#L2943-L2949
However, there are some types that can appear as `TypeVar` upper bounds
which are not represented by `Instance`, such as `UnionType` and
`CallableType`.
This PR allows such non-`Instance` upper bounds to be rendered as well.
## Effect
Consider the below code.
Playground link:
https://mypy-play.net/?mypy=1.11.2&python=3.12&enable-incomplete-feature=NewGenericSyntax&gist=ba30c820cc3668e0919dadf2f391ff4b
```python
from collections.abc import Callable
from typing import Any, overload
### No matching overloads
@overload
def f1[T: int](x: T) -> T: ...
@overload
def f1[T: Callable[..., None]](x: T) -> T: ...
@overload
def f1[T: tuple[int]](x: T) -> T: ...
@overload
def f1[T: None](x: T) -> T: ...
@overload
def f1[T: type[int]](x: T) -> T: ...
@overload
def f1[T: bytes | bytearray](x: T) -> T: ...
def f1(x): return x
f1(1.23)
### Mismatching conditional definitions
if input():
def f2[T](x: T) -> T:
return x
else:
def f2[T: Callable[..., None]](x: T) -> T:
return x
```
### Before
* In the first error on line 20, all overloads aside from the first one
are displayed as `def [T] f1(x: T) -> T` (upper bound missing).
Duplicate entries are suppressed.
* In the second error on line 28, the second definition is displayed as
`def [T] f2(x: T) -> T` (upper bound missing), and is removed as an
apparent duplicate of the first.
```none
main.py:20: error: No overload variant of "f1" matches argument type "float" [call-overload]
main.py:20: note: Possible overload variants:
main.py:20: note: def [T: int] f1(x: T) -> T
main.py:20: note: def [T] f1(x: T) -> T
main.py:28: error: All conditional function variants must have identical signatures [misc]
main.py:28: note: Original:
main.py:28: note: def [T] f2(x: T) -> T
main.py:28: note: Redefinition:
Found 2 errors in 1 file (checked 1 source file)
```
### After
* All type var upper bounds are rendered.
```none
main.py:20: error: No overload variant of "f1" matches argument type "float" [call-overload]
main.py:20: note: Possible overload variants:
main.py:20: note: def [T: int] f1(x: T) -> T
main.py:20: note: def [T: Callable[..., None]] f1(x: T) -> T
main.py:20: note: def [T: tuple[int]] f1(x: T) -> T
main.py:20: note: def [T: None] f1(x: T) -> T
main.py:20: note: def [T: type[int]] f1(x: T) -> T
main.py:20: note: def [T: bytes | bytearray] f1(x: T) -> T
main.py:28: error: All conditional function variants must have identical signatures [misc]
main.py:28: note: Original:
main.py:28: note: def [T] f2(x: T) -> T
main.py:28: note: Redefinition:
main.py:28: note: def [T: Callable[..., None]] f2(x: T) -> T
Found 2 errors in 1 file (checked 1 source file)
```1 parent 5dfc7d9 commit 94109aa
2 files changed
Lines changed: 16 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2942 | 2942 | | |
2943 | 2943 | | |
2944 | 2944 | | |
2945 | | - | |
| 2945 | + | |
2946 | 2946 | | |
2947 | | - | |
| 2947 | + | |
2948 | 2948 | | |
2949 | 2949 | | |
2950 | 2950 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1428 | 1428 | | |
1429 | 1429 | | |
1430 | 1430 | | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
1431 | 1445 | | |
1432 | 1446 | | |
1433 | 1447 | | |
| |||
0 commit comments