microsoft / microsoft/pyright

narrowing tuples using len() may be overeager

Open
#11,437 0 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.