You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bug: issubclass() doesn't narrow TypeVar type with Protocol #8556
Using issubclass with a runtime checkable Protocol and a union-bound TypeVar fails to narrow the type. The below example is from invoking mypy with mypy --python-version=3.8 reproduce-issubclass-bug.py. The issue seems similar to #7920. Tested on both 0.770 and master (0.770+dev.afe0667bbe85e048b6bb4e3fc1b7d5a375b7d01f).
fromtypingimportAnyfromtypingimportProtocolfromtypingimportruntime_checkablefromtypingimportTypefromtypingimportTypeVarfromtypingimportUnionT=TypeVar("T", bound=Any)
@runtime_checkableclassParsable(Protocol):
@classmethoddefparse(cls: Type[T], data: Any) ->T:
...
R=TypeVar("R", bound=Union[Parsable, str])
defparse_object(response_type: Type[R], item: Any) ->R:
ifissubclass(response_type, Parsable):
# note: Revealed type is 'Type[reproduce-issubclass-bug.Parsable]'reveal_type(response_type)
# error: Incompatible return value type (got "Parsable", expected "R")returnresponse_type.parse(item)
# note: Revealed type is 'Type[R`-1]'reveal_type(response_type)
# error: Too many arguments for "Parsable"# error: Incompatible return value type (got "Union[Parsable, str]", expected "R")returnresponse_type(item)
Output:
reproduce-issubclass-bug.py:25: note: Revealed type is 'Type[reproduce-issubclass-bug.Parsable]'
reproduce-issubclass-bug.py:27: error: Incompatible return value type (got "Parsable", expected "R")
reproduce-issubclass-bug.py:29: note: Revealed type is 'Type[R`-1]'
reproduce-issubclass-bug.py:32: error: Too many arguments for "Parsable"
reproduce-issubclass-bug.py:32: error: Incompatible return value type (got "Union[Parsable, str]", expected "R")
Found 3 errors in 1 file (checked 1 source file)
The narrowing seems to work to a certain extent, but mypy loses the correspondence between the type of response_type and the type variable R. This may be too difficult to for mypy to handle, so a # type: ignore or a cast will likely be required in the first return statement.
After the if statement, mypy could figure out that the type should be narrowed. However, again mypy doesn't have the notion of narrowed, dependent type variable, which would be required here.
So this would be nice to support, but it seems too complicated to be worth implementing. I'm keeping this issue open, however, in case there are other reports of this issue, or if somebody comes up with a simple way of implementing this.
Activity
JukkaL commentedon Mar 20, 2020
The narrowing seems to work to a certain extent, but mypy loses the correspondence between the type of
response_typeand the type variableR. This may be too difficult to for mypy to handle, so a# type: ignoreor a cast will likely be required in the first return statement.After the
ifstatement, mypy could figure out that the type should be narrowed. However, again mypy doesn't have the notion of narrowed, dependent type variable, which would be required here.So this would be nice to support, but it seems too complicated to be worth implementing. I'm keeping this issue open, however, in case there are other reports of this issue, or if somebody comes up with a simple way of implementing this.
antonagestam commentedon Mar 20, 2020
@JukkaL Gotcha, thanks for elaborating!
I think I'll manage to work around this by splitting the TypeVar into two and using an overload.
Narrow type variable bounds in binder (python#19183)