type inference is fragile for protocols like SupportsKeysAndGetItem
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Repro: https://mypy-play.net/?mypy=latest&python=3.11&gist=d2f8dfa1fdfda5c0c286f1a73f5e39eb
Pasted below for convenience:
import typing as t
from _typeshed import SupportsKeysAndGetItem
KT = t.TypeVar("KT")
VT = t.TypeVar("VT")
def version1(obj: SupportsKeysAndGetItem[KT, VT] | t.Iterable[tuple[KT, VT]]):
if hasattr(obj, "keys") and hasattr(obj, "__getitem__"):
reveal_type(obj) # SupportsKeysAndGetItem[KT, VT] | Iterable[tuple[KT, VT]] (as expected)
else:
reveal_type(obj) # narrowed to Iterable[tuple[KT, VT]] as expected
def version2(obj: SupportsKeysAndGetItem[KT, VT] | t.Iterable[tuple[KT, VT]]):
if hasattr(obj, "keys") and hasattr(obj, "__getitem__") and (obj_getitem := obj.__getitem__):
reveal_type(obj) # SupportsKeysAndGetItem[KT, VT] | Iterable[tuple[KT, VT]] (as expected)
else:
reveal_type(obj) # NOT narrowed
I would expect version 2 to behave the same as version 1. Is that an improvement mypy could reasonably make?
I searched for relevant docs and existing issues, but didn't find anything specifically about this. Apologies if I missed something.
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
Run the linked mypy-play repro and compare the reveal_type results in version1 and version2. Trace the type-narrowing logic for the combined hasattr checks and walrus assignment; done means version2 narrows the else branch consistently with version1, with regression coverage for the example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100