[ty] Support __setitem__ and improve __getitem__ related diagnostics (#19578)

## Summary

Adds validation to subscript assignment expressions.

```py
class Foo: ...

class Bar:
    __setattr__ = None

class Baz:
    def __setitem__(self, index: str, value: int) -> None:
        pass

# We now emit a diagnostic on these statements
Foo()[1] = 2
Bar()[1] = 2
Baz()[1] = 2

```

Also improves error messages on invalid `__getitem__` expressions

## Test Plan

Update mdtests and add more to `subscript/instance.md`

---------

Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
Co-authored-by: David Peter <mail@david-peter.de>
This commit is contained in:
Matthew Mckee
2025-08-01 08:23:27 +01:00
committed by GitHub
parent 5c5d50d57a
commit b30d97e5e0
5 changed files with 196 additions and 17 deletions

View File

@@ -253,6 +253,7 @@ does["not"]["exist"] = 0
reveal_type(does["not"]["exist"]) # revealed: Unknown
non_subscriptable = 1
# error: [invalid-assignment]
non_subscriptable[0] = 0
# error: [non-subscriptable]
reveal_type(non_subscriptable[0]) # revealed: Unknown
@@ -317,7 +318,7 @@ def f(c: C, s: str):
reveal_type(c.x) # revealed: int | None
s = c.x # error: [invalid-assignment]
# TODO: This assignment is invalid and should result in an error.
# error: [invalid-assignment] "Method `__setitem__` of type `Overload[(key: SupportsIndex, value: int, /) -> None, (key: slice[Any, Any, Any], value: Iterable[int], /) -> None]` cannot be called with a key of type `Literal[0]` and a value of type `str` on object of type `list[int]`"
c.l[0] = s
reveal_type(c.l[0]) # revealed: int
```