narrowing tuples using len() may be overeager
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
```py
from typing import reveal_type
class HasTupleAttribute:
tuple_attribute: tuple[int, ...]
def __init__(self, _tuple: tuple[int, ...]):
self.tuple_attribute = _tuple
def modify_tuple(self) -> None:
self.tuple_attribute = self.tuple_attribute[:-1]
instance = HasTupleAttribute((1, 2, 3, 4, 5))
reveal_type(instance.tuple_attribute) # Type of "instance.tuple_attribute" is "tuple[int, ...]"
assert len(instance.tuple_attribute) == 5
reveal_type(instance.tuple_attribute) # Type of "instance.tuple_attribute" is "tuple[int, int, int, int, int]"
instance.modify_tuple()
assert len(instance.tuple_attribute) == 4
reveal_type(instance.tuple_attribute) # Type of "instance.tuple_attribute" is "Never"
instance2 = HasTupleAttribute((1, 2, 3, 4, 5))
reveal_type(instance2.tuple_attribute) # Type of "instance.tuple_attribute" is "tuple[int, ...]"
assert len(instance2.tuple_attribute) == 5
reveal_type(instance2.tuple_attribute) # Type of "instance.tuple_attribute" is "tuple[int, int, int, int, int]"
instance2.tuple_attribute = instance2.tuple_attribute[:-1]
assert len(instance2.tuple_attribute) == 4
reveal_type(instance2.tuple_attribute) # Type of "instance.tuple_attribute" is "tuple[int, int, int, int]"
```
I'm experiencing this both in vscode with the Pylance plugin, and on the [pyright playground](https://pyright-play.net/?code=GYJw9gtgBALgngBwJYDsDmUkQWEMogCmAboQIYA2A%2BvAoQLABQTTAxhWQM6dQASXAFQCuCCoQCCMGCCQAjITEIAuJlDWwRYqmSkz5ipRtGEA2qhgAaKADpbAXRaN1UACaFgUKlVRIYXgBSchBTAVjSaykZiZiiWNvYAlCpOzupBIdYwEdq6cgqEUAC8nlnGqurlam4eEGAuSMBw4caBwcAJUAC0AHxQAHJgKMqVqenAmdk60nmKRVBjE8Y50-qmSp0AjA7MO6icMGQorAXF-JzCxpIr%2Bf7%2BG1YATFYAzFYALFYArAkJjkSklBoiEI-j2ByOhEWWimenyHQAxFABMCoGAPAAiMGHY5QwjLWGKdGYHjo0rRcxWWzWOzoxxcIJ4KBiFCglD7bGQsl4mEzQgdQrFT5Mf7kai0EFYiG4-G8hFIlFoqCYtngnFcmWrIlIElcmJxCmYWJWA3mGmOSU42r1RrNMT%2BX6MemERnM1nsqXqnmrfnFN7CkiioF0N2qzmTXLeqCI5F0VEYi1hpZe-Jakl9AMgWm7FUch5zM4XMRXAkgu6PF7vL4-P4BwHikO56XJxRymMFRXK91q8PXQnEpW6g1Us07J0uwgshMPJsRuFFQX%2BgFi4ENiHTz2zltR%2BWxjsJme9wipgcRPXGo2G-UX01ZphTg8lub3jeHkzrLZMMf4V3Pnsln1QH6jAinWK6-kmm58tubZxkq%2B4viWx6kqeJrXmhMA0kAA).
It seems that the possibility of side effects is being ignored, here, so it's trying to narrow to `tuple[int, ...] & len(5) & len(4)`, when it should probably be willing to narrow to `tuple[int, ...] & len(4)` despite the previous narrowing.
Contributor guide
Research direction
Start by running the provided example in the Pyright playground and compare narrowing after modify_tuple() with narrowing after direct assignment. Trace tuple-length narrowing across method calls and assignments, then add a regression test showing that stale length information is discarded after mutation while the direct-assignment case retains the new length.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100