isinstance on runtime-checkable protocols does not correctly narrow unions inferred by TypeGuard
Open
Nobody has claimed this yet.
bug
topic-type-narrowing
topic-typeguard-typeis
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
from __future__ import annotations
from collections.abc import Sized
from typing import (
Iterator,
Sequence,
)
from typing_extensions import TypeGuard
def is_list_like(x: object) -> TypeGuard[Iterator | Sequence]: # not the best example but it demonstrates the issue
...
def is_nested_list(xs: object) -> bool:
return (
is_list_like(xs)
and isinstance(xs, Sized) # after this xs is assumed to be Sized but it should be Sized while simultaneously also being an Iterator or a Sequence
and len(xs) > 0
and all(is_list_like(x) for x in xs) # "Sized" has no attribute "__iter__" (not iterable) [attr-defined]
)
Your Environment
- Mypy version used: 0.981 (same for 0.971)
- Python version used: 3.10.4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the provided reproducer and inspect mypy's handling of isinstance checks on runtime-checkable protocols after a TypeGuard narrows a union. The issue is done when xs retains the TypeGuard union while also being narrowed to Sized, so iteration and len(xs) no longer produce the reported type error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100