Skip to content

Commit db0e921

Browse files
authored
[ty] Fix bug where ty would think all types had an __mro__ attribute (#20995)
1 parent 3c7f56f commit db0e921

32 files changed

+780
-599
lines changed

crates/ty_completion_eval/completion-evaluation-tasks.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ scope-existing-over-new-import,main.py,0,474
2020
scope-prioritize-closer,main.py,0,2
2121
scope-simple-long-identifier,main.py,0,1
2222
tstring-completions,main.py,0,1
23-
ty-extensions-lower-stdlib,main.py,0,7
23+
ty-extensions-lower-stdlib,main.py,0,8
2424
type-var-typing-over-ast,main.py,0,3
2525
type-var-typing-over-ast,main.py,1,270

crates/ty_ide/src/completion.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,7 +1864,7 @@ C.<CURSOR>
18641864
__instancecheck__ :: bound method <class 'C'>.__instancecheck__(instance: Any, /) -> bool
18651865
__itemsize__ :: int
18661866
__module__ :: str
1867-
__mro__ :: tuple[<class 'C'>, <class 'object'>]
1867+
__mro__ :: tuple[type, ...]
18681868
__name__ :: str
18691869
__ne__ :: def __ne__(self, value: object, /) -> bool
18701870
__new__ :: def __new__(cls) -> Self@__new__
@@ -1933,7 +1933,7 @@ Meta.<CURSOR>
19331933
__instancecheck__ :: def __instancecheck__(self, instance: Any, /) -> bool
19341934
__itemsize__ :: int
19351935
__module__ :: str
1936-
__mro__ :: tuple[<class 'Meta'>, <class 'type'>, <class 'object'>]
1936+
__mro__ :: tuple[type, ...]
19371937
__name__ :: str
19381938
__ne__ :: def __ne__(self, value: object, /) -> bool
19391939
__or__ :: def __or__[Self](self: Self@__or__, value: Any, /) -> UnionType | Self@__or__
@@ -2061,7 +2061,7 @@ Quux.<CURSOR>
20612061
__instancecheck__ :: bound method <class 'Quux'>.__instancecheck__(instance: Any, /) -> bool
20622062
__itemsize__ :: int
20632063
__module__ :: str
2064-
__mro__ :: tuple[<class 'Quux'>, <class 'object'>]
2064+
__mro__ :: tuple[type, ...]
20652065
__name__ :: str
20662066
__ne__ :: def __ne__(self, value: object, /) -> bool
20672067
__new__ :: def __new__(cls) -> Self@__new__
@@ -2138,7 +2138,7 @@ Answer.<CURSOR>
21382138
__len__ :: bound method <class 'Answer'>.__len__() -> int
21392139
__members__ :: MappingProxyType[str, Unknown]
21402140
__module__ :: str
2141-
__mro__ :: tuple[<class 'Answer'>, <class 'Enum'>, <class 'object'>]
2141+
__mro__ :: tuple[type, ...]
21422142
__name__ :: str
21432143
__ne__ :: def __ne__(self, value: object, /) -> bool
21442144
__new__ :: def __new__(cls, value: object) -> Self@__new__

crates/ty_python_semantic/resources/mdtest/annotations/annotated.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,23 @@ Inheriting from `Annotated[T, ...]` is equivalent to inheriting from `T` itself.
7272

7373
```py
7474
from typing_extensions import Annotated
75+
from ty_extensions import reveal_mro
7576

7677
class C(Annotated[int, "foo"]): ...
7778

78-
# TODO: Should be `tuple[Literal[C], Literal[int], Literal[object]]`
79-
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, @Todo(Inference of subscript on special form), <class 'object'>]
79+
# TODO: Should be `(<class 'C'>, <class 'int'>, <class 'object'>)`
80+
reveal_mro(C) # revealed: (<class 'C'>, @Todo(Inference of subscript on special form), <class 'object'>)
8081
```
8182

8283
### Not parameterized
8384

8485
```py
8586
from typing_extensions import Annotated
87+
from ty_extensions import reveal_mro
8688

8789
# At runtime, this is an error.
8890
# error: [invalid-base]
8991
class C(Annotated): ...
9092

91-
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, Unknown, <class 'object'>]
93+
reveal_mro(C) # revealed: (<class 'C'>, Unknown, <class 'object'>)
9294
```

crates/ty_python_semantic/resources/mdtest/annotations/any.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ allowed, even when the unknown superclass is `int`. The assignment to `y` should
5656

5757
```py
5858
from typing import Any
59+
from ty_extensions import reveal_mro
5960

6061
class SubclassOfAny(Any): ...
6162

62-
reveal_type(SubclassOfAny.__mro__) # revealed: tuple[<class 'SubclassOfAny'>, Any, <class 'object'>]
63+
reveal_mro(SubclassOfAny) # revealed: (<class 'SubclassOfAny'>, Any, <class 'object'>)
6364

6465
x: SubclassOfAny = 1 # error: [invalid-assignment]
6566
y: int = SubclassOfAny()

crates/ty_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,57 +114,58 @@ The aliases can be inherited from. Some of these are still partially or wholly T
114114

115115
```py
116116
import typing
117+
from ty_extensions import reveal_mro
117118

118119
####################
119120
### Built-ins
120121
####################
121122

122123
class ListSubclass(typing.List): ...
123124

124-
# revealed: tuple[<class 'ListSubclass'>, <class 'list[Unknown]'>, <class 'MutableSequence[Unknown]'>, <class 'Sequence[Unknown]'>, <class 'Reversible[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
125-
reveal_type(ListSubclass.__mro__)
125+
# revealed: (<class 'ListSubclass'>, <class 'list[Unknown]'>, <class 'MutableSequence[Unknown]'>, <class 'Sequence[Unknown]'>, <class 'Reversible[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
126+
reveal_mro(ListSubclass)
126127

127128
class DictSubclass(typing.Dict): ...
128129

129-
# revealed: tuple[<class 'DictSubclass'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
130-
reveal_type(DictSubclass.__mro__)
130+
# revealed: (<class 'DictSubclass'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
131+
reveal_mro(DictSubclass)
131132

132133
class SetSubclass(typing.Set): ...
133134

134-
# revealed: tuple[<class 'SetSubclass'>, <class 'set[Unknown]'>, <class 'MutableSet[Unknown]'>, <class 'AbstractSet[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
135-
reveal_type(SetSubclass.__mro__)
135+
# revealed: (<class 'SetSubclass'>, <class 'set[Unknown]'>, <class 'MutableSet[Unknown]'>, <class 'AbstractSet[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
136+
reveal_mro(SetSubclass)
136137

137138
class FrozenSetSubclass(typing.FrozenSet): ...
138139

139-
# revealed: tuple[<class 'FrozenSetSubclass'>, <class 'frozenset[Unknown]'>, <class 'AbstractSet[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
140-
reveal_type(FrozenSetSubclass.__mro__)
140+
# revealed: (<class 'FrozenSetSubclass'>, <class 'frozenset[Unknown]'>, <class 'AbstractSet[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
141+
reveal_mro(FrozenSetSubclass)
141142

142143
####################
143144
### `collections`
144145
####################
145146

146147
class ChainMapSubclass(typing.ChainMap): ...
147148

148-
# revealed: tuple[<class 'ChainMapSubclass'>, <class 'ChainMap[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
149-
reveal_type(ChainMapSubclass.__mro__)
149+
# revealed: (<class 'ChainMapSubclass'>, <class 'ChainMap[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
150+
reveal_mro(ChainMapSubclass)
150151

151152
class CounterSubclass(typing.Counter): ...
152153

153-
# revealed: tuple[<class 'CounterSubclass'>, <class 'Counter[Unknown]'>, <class 'dict[Unknown, int]'>, <class 'MutableMapping[Unknown, int]'>, <class 'Mapping[Unknown, int]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
154-
reveal_type(CounterSubclass.__mro__)
154+
# revealed: (<class 'CounterSubclass'>, <class 'Counter[Unknown]'>, <class 'dict[Unknown, int]'>, <class 'MutableMapping[Unknown, int]'>, <class 'Mapping[Unknown, int]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
155+
reveal_mro(CounterSubclass)
155156

156157
class DefaultDictSubclass(typing.DefaultDict): ...
157158

158-
# revealed: tuple[<class 'DefaultDictSubclass'>, <class 'defaultdict[Unknown, Unknown]'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
159-
reveal_type(DefaultDictSubclass.__mro__)
159+
# revealed: (<class 'DefaultDictSubclass'>, <class 'defaultdict[Unknown, Unknown]'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
160+
reveal_mro(DefaultDictSubclass)
160161

161162
class DequeSubclass(typing.Deque): ...
162163

163-
# revealed: tuple[<class 'DequeSubclass'>, <class 'deque[Unknown]'>, <class 'MutableSequence[Unknown]'>, <class 'Sequence[Unknown]'>, <class 'Reversible[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
164-
reveal_type(DequeSubclass.__mro__)
164+
# revealed: (<class 'DequeSubclass'>, <class 'deque[Unknown]'>, <class 'MutableSequence[Unknown]'>, <class 'Sequence[Unknown]'>, <class 'Reversible[Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
165+
reveal_mro(DequeSubclass)
165166

166167
class OrderedDictSubclass(typing.OrderedDict): ...
167168

168-
# revealed: tuple[<class 'OrderedDictSubclass'>, <class 'OrderedDict[Unknown, Unknown]'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>]
169-
reveal_type(OrderedDictSubclass.__mro__)
169+
# revealed: (<class 'OrderedDictSubclass'>, <class 'OrderedDict[Unknown, Unknown]'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection[Unknown]'>, <class 'Iterable[Unknown]'>, <class 'Container[Unknown]'>, typing.Protocol, typing.Generic, <class 'object'>)
170+
reveal_mro(OrderedDictSubclass)
170171
```

crates/ty_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ You can't inherit from most of these. `typing.Callable` is an exception.
7878
```py
7979
from typing import Callable
8080
from typing_extensions import Self, Unpack, TypeGuard, TypeIs, Concatenate, Generic
81+
from ty_extensions import reveal_mro
8182

8283
class A(Self): ... # error: [invalid-base]
8384
class B(Unpack): ... # error: [invalid-base]
@@ -87,7 +88,7 @@ class E(Concatenate): ... # error: [invalid-base]
8788
class F(Callable): ...
8889
class G(Generic): ... # error: [invalid-base] "Cannot inherit from plain `Generic`"
8990

90-
reveal_type(F.__mro__) # revealed: tuple[<class 'F'>, @Todo(Support for Callable as a base class), <class 'object'>]
91+
reveal_mro(F) # revealed: (<class 'F'>, @Todo(Support for Callable as a base class), <class 'object'>)
9192
```
9293

9394
## Subscriptability

crates/ty_python_semantic/resources/mdtest/attributes.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,8 @@ C.X = "bar"
14681468
### Multiple inheritance
14691469

14701470
```py
1471+
from ty_extensions import reveal_mro
1472+
14711473
class O: ...
14721474

14731475
class F(O):
@@ -1481,8 +1483,8 @@ class C(D, F): ...
14811483
class B(E, D): ...
14821484
class A(B, C): ...
14831485

1484-
# revealed: tuple[<class 'A'>, <class 'B'>, <class 'E'>, <class 'C'>, <class 'D'>, <class 'F'>, <class 'O'>, <class 'object'>]
1485-
reveal_type(A.__mro__)
1486+
# revealed: (<class 'A'>, <class 'B'>, <class 'E'>, <class 'C'>, <class 'D'>, <class 'F'>, <class 'O'>, <class 'object'>)
1487+
reveal_mro(A)
14861488

14871489
# `E` is earlier in the MRO than `F`, so we should use the type of `E.X`
14881490
reveal_type(A.X) # revealed: Unknown | Literal[42]
@@ -1682,14 +1684,15 @@ Similar principles apply if `Any` appears in the middle of an inheritance hierar
16821684

16831685
```py
16841686
from typing import ClassVar, Literal
1687+
from ty_extensions import reveal_mro
16851688

16861689
class A:
16871690
x: ClassVar[Literal[1]] = 1
16881691

16891692
class B(Any): ...
16901693
class C(B, A): ...
16911694

1692-
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, Any, <class 'A'>, <class 'object'>]
1695+
reveal_mro(C) # revealed: (<class 'C'>, <class 'B'>, Any, <class 'A'>, <class 'object'>)
16931696
reveal_type(C.x) # revealed: Literal[1] & Any
16941697
```
16951698

crates/ty_python_semantic/resources/mdtest/class/super.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ python-version = "3.12"
2626

2727
```py
2828
from __future__ import annotations
29+
from ty_extensions import reveal_mro
2930

3031
class A:
3132
def a(self): ...
@@ -39,7 +40,7 @@ class C(B):
3940
def c(self): ...
4041
cc: int = 3
4142

42-
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>]
43+
reveal_mro(C) # revealed: (<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>)
4344

4445
super(C, C()).a
4546
super(C, C()).b
@@ -420,6 +421,8 @@ When the owner is a union type, `super()` is built separately for each branch, a
420421
super objects are combined into a union.
421422

422423
```py
424+
from ty_extensions import reveal_mro
425+
423426
class A: ...
424427

425428
class B:
@@ -429,8 +432,8 @@ class C(A, B): ...
429432
class D(B, A): ...
430433

431434
def f(x: C | D):
432-
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>]
433-
reveal_type(D.__mro__) # revealed: tuple[<class 'D'>, <class 'B'>, <class 'A'>, <class 'object'>]
435+
reveal_mro(C) # revealed: (<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>)
436+
reveal_mro(D) # revealed: (<class 'D'>, <class 'B'>, <class 'A'>, <class 'object'>)
434437

435438
s = super(A, x)
436439
reveal_type(s) # revealed: <super: <class 'A'>, C> | <super: <class 'A'>, D>

crates/ty_python_semantic/resources/mdtest/classes.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ python-version = "3.12"
1313
```
1414

1515
```py
16+
from ty_extensions import reveal_mro
17+
1618
A = int
1719

1820
class G[T]: ...
@@ -21,5 +23,5 @@ class C(A, G["B"]): ...
2123
A = str
2224
B = bytes
2325

24-
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'int'>, <class 'G[bytes]'>, typing.Generic, <class 'object'>]
26+
reveal_mro(C) # revealed: (<class 'C'>, <class 'int'>, <class 'G[bytes]'>, typing.Generic, <class 'object'>)
2527
```

crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,14 +1173,16 @@ and attributes like the MRO are unchanged:
11731173

11741174
```py
11751175
from dataclasses import dataclass
1176+
from ty_extensions import reveal_mro
11761177

11771178
@dataclass
11781179
class Person:
11791180
name: str
11801181
age: int | None = None
11811182

11821183
reveal_type(type(Person)) # revealed: <class 'type'>
1183-
reveal_type(Person.__mro__) # revealed: tuple[<class 'Person'>, <class 'object'>]
1184+
reveal_type(Person.__mro__) # revealed: tuple[type, ...]
1185+
reveal_mro(Person) # revealed: (<class 'Person'>, <class 'object'>)
11841186
```
11851187

11861188
The generated methods have the following signatures:

0 commit comments

Comments
 (0)