[ty] add support for mapped union and intersection subscript loads (#18846)

## Summary

Note this modifies the diagnostics a bit. Previously performing
subscript access on something like `NotSubscriptable1 |
NotSubscriptable2` would report the full type as not being
subscriptable:

```
[non-subscriptable] "Cannot subscript object of type `NotSubscriptable1 | NotSubscriptable2` with no `__getitem__` method"
```

Now each erroneous constituent has a separate error:

```
[non-subscriptable] "Cannot subscript object of type `NotSubscriptable2` with no `__getitem__` method"
[non-subscriptable] "Cannot subscript object of type `NotSubscriptable1` with no `__getitem__` method"
```

Closes https://github.com/astral-sh/ty/issues/625

## Test Plan

 mdtest

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
Suneet Tipirneni
2025-06-23 12:38:01 -04:00
committed by GitHub
parent a77db3da3f
commit ef8281b695
5 changed files with 54 additions and 24 deletions

View File

@@ -63,12 +63,12 @@ def _(flag: bool):
else:
class Spam: ...
# error: [possibly-unbound-implicit-call] "Method `__class_getitem__` of type `<class 'Spam'> | <class 'Spam'>` is possibly unbound"
# revealed: str
# error: [non-subscriptable] "Cannot subscript object of type `<class 'Spam'>` with no `__class_getitem__` method"
# revealed: str | Unknown
reveal_type(Spam[42])
```
## TODO: Class getitem non-class union
## Class getitem non-class union
```py
def _(flag: bool):
@@ -80,8 +80,7 @@ def _(flag: bool):
else:
Eggs = 1
a = Eggs[42] # error: "Cannot subscript object of type `<class 'Eggs'> | Literal[1]` with no `__getitem__` method"
a = Eggs[42] # error: "Cannot subscript object of type `Literal[1]` with no `__getitem__` method"
# TODO: should _probably_ emit `str | Unknown`
reveal_type(a) # revealed: Unknown
reveal_type(a) # revealed: str | Unknown
```