Closed as not planned
Closed as not planned
Description
Bug Report
I found a really weird bug while writing a decorator that returns a Protocol
that itself uses a concatenated ParamSpec
. I managed to get to a small reproducible example:
P = ParamSpec("P")
T = TypeVar("T")
X = TypeVar("X")
class Wrapped(Protocol[P, T]):
__call__: Callable[P, T]
def decorator(
func: Callable[Concatenate[X, P], T],
) -> Wrapped[Concatenate[X, P], T]:
# Do something with X
return func
@decorator
def first(
source: Iterable[T],
) -> T:
return next(iter(source))
item = first(range(2))
reveal_type(item)
print(item.real)
Expected Behavior
It works as expected using either one of those two decorators instead:
# Decorator without `Concatenate`
def decorator(
func: Callable[P, T],
) -> Wrapped[P, T]:
# Do something with X
return func
# Decorator without `Protocol`
def decorator(
func: Callable[Concatenate[X, P], T],
) -> Callable[Concatenate[X, P], T]:
# Do something with X
return func
In those two cases, mypy is happy and reports an int
as expected:
note: Revealed type is "builtins.int"
Actual Behavior
Instead, mypy is confused and expects i
to be a range
:
note: Revealed type is "builtins.range"
error: "range" has no attribute "upper" [attr-defined]
Your Environment
- Mypy version used:
v1.4.1
andmypy 1.6.0+dev.d2022a0007c0eb176ccaf37a9aa54c958be7fb10 (compiled: no)
- Python version used:
3.10.4
and3.11