From ad483da171bf8221f14f3be98ccfb0c5d3b19e48 Mon Sep 17 00:00:00 2001 From: InSyncWithFoo Date: Mon, 16 Dec 2024 00:16:44 +0000 Subject: [PATCH 1/8] [red-knot] Understand other legacy `typing` aliases --- .../annotations/stdlib_typing_aliases.md | 118 +++++++++++------- crates/red_knot_python_semantic/src/stdlib.rs | 2 + crates/red_knot_python_semantic/src/types.rs | 85 +++++++++++-- .../src/types/infer.rs | 48 ++----- 4 files changed, 164 insertions(+), 89 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index 452fa9f015e24..ca95da01a5d62 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -3,43 +3,59 @@ The `typing` module has various aliases to other stdlib classes. These are a legacy feature, but still need to be supported by a type checker. -## Currently unsupported +## Correspondence -Support for most of these symbols is currently a TODO: +All of the following symbols can be mapped one-to-one with the actual type: ```py import typing def f( - a: typing.List, - b: typing.List[int], - c: typing.Dict, - d: typing.Dict[int, str], - e: typing.DefaultDict, - f: typing.DefaultDict[str, int], - g: typing.Set, - h: typing.Set[int], - i: typing.FrozenSet, - j: typing.FrozenSet[str], - k: typing.OrderedDict, - l: typing.OrderedDict[int, str], - m: typing.Counter, - n: typing.Counter[int], + list_bare: typing.List, + list_parametrized: typing.List[int], + dict_bare: typing.Dict, + dict_parametrized: typing.Dict[int, str], + set_bare: typing.Set, + set_parametrized: typing.Set[int], + frozen_set_bare: typing.FrozenSet, + frozen_set_parametrized: typing.FrozenSet[str], + chain_map_bare: typing.ChainMap, + chain_map_parametrized: typing.ChainMap[int], + counter_bare: typing.Counter, + counter_parametrized: typing.Counter[int], + default_dict_bare: typing.DefaultDict, + default_dict_parametrized: typing.DefaultDict[str, int], + deque_bare: typing.Deque, + deque_parametrized: typing.Deque[str], + ordered_dict_bare: typing.OrderedDict, + ordered_dict_parametrized: typing.OrderedDict[int, str], ): - reveal_type(a) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(b) # revealed: @Todo(typing.List alias) - reveal_type(c) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(d) # revealed: @Todo(typing.Dict alias) - reveal_type(e) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(f) # revealed: @Todo(typing.DefaultDict[] alias) - reveal_type(g) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(h) # revealed: @Todo(typing.Set alias) - reveal_type(i) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(j) # revealed: @Todo(typing.FrozenSet alias) - reveal_type(k) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(l) # revealed: @Todo(typing.OrderedDict alias) - reveal_type(m) # revealed: @Todo(Unsupported or invalid type in a type expression) - reveal_type(n) # revealed: @Todo(typing.Counter[] alias) + reveal_type(list_bare) # revealed: list + reveal_type(list_parametrized) # revealed: list + + reveal_type(dict_bare) # revealed: dict + reveal_type(dict_parametrized) # revealed: dict + + reveal_type(set_bare) # revealed: set + reveal_type(set_parametrized) # revealed: set + + reveal_type(frozen_set_bare) # revealed: frozenset + reveal_type(frozen_set_parametrized) # revealed: frozenset + + reveal_type(chain_map_bare) # revealed: ChainMap + reveal_type(chain_map_parametrized) # revealed: ChainMap + + reveal_type(counter_bare) # revealed: Counter + reveal_type(counter_parametrized) # revealed: Counter + + reveal_type(default_dict_bare) # revealed: defaultdict + reveal_type(default_dict_parametrized) # revealed: defaultdict + + reveal_type(deque_bare) # revealed: deque + reveal_type(deque_parametrized) # revealed: deque + + reveal_type(ordered_dict_bare) # revealed: OrderedDict + reveal_type(ordered_dict_parametrized) # revealed: OrderedDict ``` ## Inheritance @@ -49,35 +65,49 @@ The aliases can be inherited from. Some of these are still partially or wholly T ```py import typing -class A(typing.Dict): ... +#################### +### Built-ins + +class _List(typing.List): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[dict], Unknown, Literal[object]] +reveal_type(_List.__mro__) # revealed: tuple[Literal[_List], Literal[list], Unknown, Literal[object]] -class B(typing.List): ... +class _Dict(typing.Dict): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[list], Unknown, Literal[object]] +reveal_type(_Dict.__mro__) # revealed: tuple[Literal[_Dict], Literal[dict], Unknown, Literal[object]] -class C(typing.Set): ... +class _Set(typing.Set): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[set], Unknown, Literal[object]] +reveal_type(_Set.__mro__) # revealed: tuple[Literal[_Set], Literal[set], Unknown, Literal[object]] -class D(typing.FrozenSet): ... +class _FrozenSet(typing.FrozenSet): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(D.__mro__) # revealed: tuple[Literal[D], Literal[frozenset], Unknown, Literal[object]] +reveal_type(_FrozenSet.__mro__) # revealed: tuple[Literal[_FrozenSet], Literal[frozenset], Unknown, Literal[object]] + +#################### +### `collections` + +class _ChainMap(typing.ChainMap): ... + +reveal_type(_ChainMap.__mro__) # revealed: tuple[Literal[_ChainMap], @Todo(Support for more typing aliases as base classes), Literal[object]] + +class _Counter(typing.Counter): ... + +reveal_type(_Counter.__mro__) # revealed: tuple[Literal[_Counter], @Todo(Support for more typing aliases as base classes), Literal[object]] -class E(typing.DefaultDict): ... +class _DefaultDict(typing.DefaultDict): ... -reveal_type(E.__mro__) # revealed: tuple[Literal[E], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_DefaultDict.__mro__) # revealed: tuple[Literal[_DefaultDict], @Todo(Support for more typing aliases as base classes), Literal[object]] -class F(typing.OrderedDict): ... +class _Deque(typing.Deque): ... -reveal_type(F.__mro__) # revealed: tuple[Literal[F], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_Deque.__mro__) # revealed: tuple[Literal[_Deque], @Todo(Support for more typing aliases as base classes), Literal[object]] -class G(typing.Counter): ... +class _OrderedDict(typing.OrderedDict): ... -reveal_type(G.__mro__) # revealed: tuple[Literal[G], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_OrderedDict.__mro__) # revealed: tuple[Literal[_OrderedDict], @Todo(Support for more typing aliases as base classes), Literal[object]] ``` diff --git a/crates/red_knot_python_semantic/src/stdlib.rs b/crates/red_knot_python_semantic/src/stdlib.rs index 56f3c984bcbc2..2ab2fa2331434 100644 --- a/crates/red_knot_python_semantic/src/stdlib.rs +++ b/crates/red_knot_python_semantic/src/stdlib.rs @@ -17,6 +17,7 @@ pub(crate) enum CoreStdlibModule { Sys, #[allow(dead_code)] Abc, // currently only used in tests + Collections, } impl CoreStdlibModule { @@ -29,6 +30,7 @@ impl CoreStdlibModule { Self::TypingExtensions => "typing_extensions", Self::Sys => "sys", Self::Abc => "abc", + Self::Collections => "collections", } } diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index b714f3b0f9636..93bc61af55cf5 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -1380,6 +1380,11 @@ impl<'db> Type<'db> { | KnownClass::ModuleType | KnownClass::FunctionType | KnownClass::SpecialForm + | KnownClass::ChainMap + | KnownClass::Counter + | KnownClass::DefaultDict + | KnownClass::Deque + | KnownClass::OrderedDict | KnownClass::StdlibAlias | KnownClass::TypeVar, ) => false, @@ -1892,6 +1897,28 @@ impl<'db> Type<'db> { // We treat `typing.Type` exactly the same as `builtins.type`: Type::KnownInstance(KnownInstanceType::Type) => Ok(KnownClass::Type.to_instance(db)), Type::KnownInstance(KnownInstanceType::Tuple) => Ok(KnownClass::Tuple.to_instance(db)), + + // Legacy `typing` aliases + Type::KnownInstance(KnownInstanceType::List) => Ok(KnownClass::List.to_instance(db)), + Type::KnownInstance(KnownInstanceType::Dict) => Ok(KnownClass::Dict.to_instance(db)), + Type::KnownInstance(KnownInstanceType::Set) => Ok(KnownClass::Set.to_instance(db)), + Type::KnownInstance(KnownInstanceType::FrozenSet) => { + Ok(KnownClass::FrozenSet.to_instance(db)) + } + Type::KnownInstance(KnownInstanceType::ChainMap) => { + Ok(KnownClass::ChainMap.to_instance(db)) + } + Type::KnownInstance(KnownInstanceType::Counter) => { + Ok(KnownClass::Counter.to_instance(db)) + } + Type::KnownInstance(KnownInstanceType::DefaultDict) => { + Ok(KnownClass::DefaultDict.to_instance(db)) + } + Type::KnownInstance(KnownInstanceType::Deque) => Ok(KnownClass::Deque.to_instance(db)), + Type::KnownInstance(KnownInstanceType::OrderedDict) => { + Ok(KnownClass::OrderedDict.to_instance(db)) + } + Type::Union(union) => { let mut builder = UnionBuilder::new(db); let mut invalid_expressions = smallvec::SmallVec::default(); @@ -2153,6 +2180,12 @@ pub enum KnownClass { TypeVar, TypeAliasType, NoDefaultType, + // Collections + ChainMap, + Counter, + DefaultDict, + Deque, + OrderedDict, // sys VersionInfo, } @@ -2183,6 +2216,11 @@ impl<'db> KnownClass { Self::TypeVar => "TypeVar", Self::TypeAliasType => "TypeAliasType", Self::NoDefaultType => "_NoDefaultType", + Self::ChainMap => "ChainMap", + Self::Counter => "Counter", + Self::DefaultDict => "defaultdict", + Self::Deque => "deque", + Self::OrderedDict => "OrderedDict", // For example, `typing.List` is defined as `List = _Alias()` in typeshed Self::StdlibAlias => "_Alias", // This is the name the type of `sys.version_info` has in typeshed, @@ -2246,6 +2284,11 @@ impl<'db> KnownClass { CoreStdlibModule::TypingExtensions } } + Self::ChainMap + | Self::Counter + | Self::DefaultDict + | Self::Deque + | Self::OrderedDict => CoreStdlibModule::Collections, } } @@ -2273,6 +2316,11 @@ impl<'db> KnownClass { | Self::ModuleType | Self::FunctionType | Self::SpecialForm + | Self::ChainMap + | Self::Counter + | Self::DefaultDict + | Self::Deque + | Self::OrderedDict | Self::StdlibAlias | Self::BaseException | Self::BaseExceptionGroup @@ -2305,6 +2353,11 @@ impl<'db> KnownClass { "ModuleType" => Self::ModuleType, "FunctionType" => Self::FunctionType, "TypeAliasType" => Self::TypeAliasType, + "ChainMap" => Self::ChainMap, + "Counter" => Self::Counter, + "defaultdict" => Self::DefaultDict, + "deque" => Self::Deque, + "OrderedDict" => Self::OrderedDict, "_Alias" => Self::StdlibAlias, "_SpecialForm" => Self::SpecialForm, "_NoDefaultType" => Self::NoDefaultType, @@ -2336,6 +2389,11 @@ impl<'db> KnownClass { | Self::Dict | Self::Slice | Self::GenericAlias + | Self::ChainMap + | Self::Counter + | Self::DefaultDict + | Self::Deque + | Self::OrderedDict | Self::StdlibAlias // no equivalent class exists in typing_extensions, nor ever will | Self::ModuleType | Self::VersionInfo @@ -2371,6 +2429,24 @@ pub enum KnownInstanceType<'db> { Any, /// The symbol `typing.Tuple` (which can also be found as `typing_extensions.Tuple`) Tuple, + /// The symbol `typing.List` (which can also be found as `typing_extensions.List`) + List, + /// The symbol `typing.Dict` (which can also be found as `typing_extensions.Dict`) + Dict, + /// The symbol `typing.Set` (which can also be found as `typing_extensions.Set`) + Set, + /// The symbol `typing.FrozenSet` (which can also be found as `typing_extensions.FrozenSet`) + FrozenSet, + /// The symbol `typing.ChainMap` (which can also be found as `typing_extensions.ChainMap`) + ChainMap, + /// The symbol `typing.Counter` (which can also be found as `typing_extensions.Counter`) + Counter, + /// The symbol `typing.DefaultDict` (which can also be found as `typing_extensions.DefaultDict`) + DefaultDict, + /// The symbol `typing.Deque` (which can also be found as `typing_extensions.Deque`) + Deque, + /// The symbol `typing.OrderedDict` (which can also be found as `typing_extensions.OrderedDict`) + OrderedDict, /// The symbol `typing.Type` (which can also be found as `typing_extensions.Type`) Type, /// A single instance of `typing.TypeVar` @@ -2391,15 +2467,6 @@ pub enum KnownInstanceType<'db> { TypeAlias, TypeGuard, TypeIs, - List, - Dict, - DefaultDict, - Set, - FrozenSet, - Counter, - Deque, - ChainMap, - OrderedDict, ReadOnly, // TODO: fill this enum out with more special forms, etc. } diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 5c868163e3b69..92081c2cf4fae 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -4904,42 +4904,18 @@ impl<'db> TypeInferenceBuilder<'db> { self.infer_type_expression(arguments_slice); todo_type!("Callable types") } - KnownInstanceType::ChainMap => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.ChainMap alias") - } - KnownInstanceType::OrderedDict => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.OrderedDict alias") - } - KnownInstanceType::Dict => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.Dict alias") - } - KnownInstanceType::List => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.List alias") - } - KnownInstanceType::DefaultDict => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.DefaultDict[] alias") - } - KnownInstanceType::Counter => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.Counter[] alias") - } - KnownInstanceType::Set => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.Set alias") - } - KnownInstanceType::FrozenSet => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.FrozenSet alias") - } - KnownInstanceType::Deque => { - self.infer_type_expression(arguments_slice); - todo_type!("typing.Deque alias") - } + + // TODO: Generics + KnownInstanceType::ChainMap => KnownClass::ChainMap.to_instance(self.db), + KnownInstanceType::OrderedDict => KnownClass::OrderedDict.to_instance(self.db), + KnownInstanceType::Dict => KnownClass::Dict.to_instance(self.db), + KnownInstanceType::List => KnownClass::List.to_instance(self.db), + KnownInstanceType::DefaultDict => KnownClass::DefaultDict.to_instance(self.db), + KnownInstanceType::Counter => KnownClass::Counter.to_instance(self.db), + KnownInstanceType::Set => KnownClass::Set.to_instance(self.db), + KnownInstanceType::FrozenSet => KnownClass::FrozenSet.to_instance(self.db), + KnownInstanceType::Deque => KnownClass::Deque.to_instance(self.db), + KnownInstanceType::ReadOnly => { self.infer_type_expression(arguments_slice); todo_type!("Required[] type qualifier") From 2e97d5ad88b2249a668ce3bbabc60b975b4c95e7 Mon Sep 17 00:00:00 2001 From: InSyncWithFoo Date: Mon, 16 Dec 2024 00:34:15 +0000 Subject: [PATCH 2/8] Fix panic --- .../src/types/infer.rs | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 92081c2cf4fae..326345fb30543 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -4906,15 +4906,42 @@ impl<'db> TypeInferenceBuilder<'db> { } // TODO: Generics - KnownInstanceType::ChainMap => KnownClass::ChainMap.to_instance(self.db), - KnownInstanceType::OrderedDict => KnownClass::OrderedDict.to_instance(self.db), - KnownInstanceType::Dict => KnownClass::Dict.to_instance(self.db), - KnownInstanceType::List => KnownClass::List.to_instance(self.db), - KnownInstanceType::DefaultDict => KnownClass::DefaultDict.to_instance(self.db), - KnownInstanceType::Counter => KnownClass::Counter.to_instance(self.db), - KnownInstanceType::Set => KnownClass::Set.to_instance(self.db), - KnownInstanceType::FrozenSet => KnownClass::FrozenSet.to_instance(self.db), - KnownInstanceType::Deque => KnownClass::Deque.to_instance(self.db), + KnownInstanceType::ChainMap => { + self.infer_type_expression(arguments_slice); + KnownClass::ChainMap.to_instance(self.db) + } + KnownInstanceType::OrderedDict => { + self.infer_type_expression(arguments_slice); + KnownClass::OrderedDict.to_instance(self.db) + } + KnownInstanceType::Dict => { + self.infer_type_expression(arguments_slice); + KnownClass::Dict.to_instance(self.db) + } + KnownInstanceType::List => { + self.infer_type_expression(arguments_slice); + KnownClass::List.to_instance(self.db) + } + KnownInstanceType::DefaultDict => { + self.infer_type_expression(arguments_slice); + KnownClass::DefaultDict.to_instance(self.db) + } + KnownInstanceType::Counter => { + self.infer_type_expression(arguments_slice); + KnownClass::Counter.to_instance(self.db) + } + KnownInstanceType::Set => { + self.infer_type_expression(arguments_slice); + KnownClass::Set.to_instance(self.db) + } + KnownInstanceType::FrozenSet => { + self.infer_type_expression(arguments_slice); + KnownClass::FrozenSet.to_instance(self.db) + } + KnownInstanceType::Deque => { + self.infer_type_expression(arguments_slice); + KnownClass::Deque.to_instance(self.db) + } KnownInstanceType::ReadOnly => { self.infer_type_expression(arguments_slice); From f33537ce5cf39facafe773da58d3ae6459c72f51 Mon Sep 17 00:00:00 2001 From: InSync Date: Mon, 16 Dec 2024 00:49:04 +0000 Subject: [PATCH 3/8] Formatting --- .../annotations/stdlib_typing_aliases.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index ca95da01a5d62..1c41a358a2f1e 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -93,21 +93,31 @@ reveal_type(_FrozenSet.__mro__) # revealed: tuple[Literal[_FrozenSet], Literal[ class _ChainMap(typing.ChainMap): ... -reveal_type(_ChainMap.__mro__) # revealed: tuple[Literal[_ChainMap], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type( + _ChainMap.__mro__ +) # revealed: tuple[Literal[_ChainMap], @Todo(Support for more typing aliases as base classes), Literal[object]] class _Counter(typing.Counter): ... -reveal_type(_Counter.__mro__) # revealed: tuple[Literal[_Counter], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type( + _Counter.__mro__ +) # revealed: tuple[Literal[_Counter], @Todo(Support for more typing aliases as base classes), Literal[object]] class _DefaultDict(typing.DefaultDict): ... -reveal_type(_DefaultDict.__mro__) # revealed: tuple[Literal[_DefaultDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type( + _DefaultDict.__mro__ +) # revealed: tuple[Literal[_DefaultDict], @Todo(Support for more typing aliases as base classes), Literal[object]] class _Deque(typing.Deque): ... -reveal_type(_Deque.__mro__) # revealed: tuple[Literal[_Deque], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type( + _Deque.__mro__ +) # revealed: tuple[Literal[_Deque], @Todo(Support for more typing aliases as base classes), Literal[object]] class _OrderedDict(typing.OrderedDict): ... -reveal_type(_OrderedDict.__mro__) # revealed: tuple[Literal[_OrderedDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type( + _OrderedDict.__mro__ +) # revealed: tuple[Literal[_OrderedDict], @Todo(Support for more typing aliases as base classes), Literal[object]] ``` From 14074674f909f9bde08e7636b5ca33701646d587 Mon Sep 17 00:00:00 2001 From: InSync Date: Mon, 16 Dec 2024 08:19:25 +0700 Subject: [PATCH 4/8] Fix --- .../annotations/stdlib_typing_aliases.md | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index 1c41a358a2f1e..dbbe09559ed85 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -93,31 +93,26 @@ reveal_type(_FrozenSet.__mro__) # revealed: tuple[Literal[_FrozenSet], Literal[ class _ChainMap(typing.ChainMap): ... -reveal_type( - _ChainMap.__mro__ -) # revealed: tuple[Literal[_ChainMap], @Todo(Support for more typing aliases as base classes), Literal[object]] +# revealed: tuple[Literal[_ChainMap], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_ChainMap.__mro__) class _Counter(typing.Counter): ... -reveal_type( - _Counter.__mro__ -) # revealed: tuple[Literal[_Counter], @Todo(Support for more typing aliases as base classes), Literal[object]] +# revealed: tuple[Literal[_Counter], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_Counter.__mro__) class _DefaultDict(typing.DefaultDict): ... -reveal_type( - _DefaultDict.__mro__ -) # revealed: tuple[Literal[_DefaultDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +# revealed: tuple[Literal[_DefaultDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_DefaultDict.__mro__) class _Deque(typing.Deque): ... -reveal_type( - _Deque.__mro__ -) # revealed: tuple[Literal[_Deque], @Todo(Support for more typing aliases as base classes), Literal[object]] +# revealed: tuple[Literal[_Deque], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_Deque.__mro__) class _OrderedDict(typing.OrderedDict): ... -reveal_type( - _OrderedDict.__mro__ -) # revealed: tuple[Literal[_OrderedDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +# revealed: tuple[Literal[_OrderedDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(_OrderedDict.__mro__) ``` From 0275d7d465dd5996f480fdbfb5159270af484b9a Mon Sep 17 00:00:00 2001 From: InSyncWithFoo Date: Mon, 16 Dec 2024 17:38:03 +0000 Subject: [PATCH 5/8] `ClassBase::try_from_ty` --- .../annotations/stdlib_typing_aliases.md | 87 ++++++++++--------- .../src/types/class_base.rs | 22 +++-- 2 files changed, 62 insertions(+), 47 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index dbbe09559ed85..a5505e6c95269 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -11,51 +11,51 @@ All of the following symbols can be mapped one-to-one with the actual type: import typing def f( - list_bare: typing.List, - list_parametrized: typing.List[int], - dict_bare: typing.Dict, - dict_parametrized: typing.Dict[int, str], - set_bare: typing.Set, - set_parametrized: typing.Set[int], - frozen_set_bare: typing.FrozenSet, - frozen_set_parametrized: typing.FrozenSet[str], - chain_map_bare: typing.ChainMap, - chain_map_parametrized: typing.ChainMap[int], - counter_bare: typing.Counter, - counter_parametrized: typing.Counter[int], - default_dict_bare: typing.DefaultDict, - default_dict_parametrized: typing.DefaultDict[str, int], - deque_bare: typing.Deque, - deque_parametrized: typing.Deque[str], - ordered_dict_bare: typing.OrderedDict, - ordered_dict_parametrized: typing.OrderedDict[int, str], + list_bare: typing.List, + list_parametrized: typing.List[int], + dict_bare: typing.Dict, + dict_parametrized: typing.Dict[int, str], + set_bare: typing.Set, + set_parametrized: typing.Set[int], + frozen_set_bare: typing.FrozenSet, + frozen_set_parametrized: typing.FrozenSet[str], + chain_map_bare: typing.ChainMap, + chain_map_parametrized: typing.ChainMap[int], + counter_bare: typing.Counter, + counter_parametrized: typing.Counter[int], + default_dict_bare: typing.DefaultDict, + default_dict_parametrized: typing.DefaultDict[str, int], + deque_bare: typing.Deque, + deque_parametrized: typing.Deque[str], + ordered_dict_bare: typing.OrderedDict, + ordered_dict_parametrized: typing.OrderedDict[int, str], ): - reveal_type(list_bare) # revealed: list - reveal_type(list_parametrized) # revealed: list + reveal_type(list_bare) # revealed: list + reveal_type(list_parametrized) # revealed: list - reveal_type(dict_bare) # revealed: dict - reveal_type(dict_parametrized) # revealed: dict + reveal_type(dict_bare) # revealed: dict + reveal_type(dict_parametrized) # revealed: dict - reveal_type(set_bare) # revealed: set - reveal_type(set_parametrized) # revealed: set + reveal_type(set_bare) # revealed: set + reveal_type(set_parametrized) # revealed: set - reveal_type(frozen_set_bare) # revealed: frozenset - reveal_type(frozen_set_parametrized) # revealed: frozenset + reveal_type(frozen_set_bare) # revealed: frozenset + reveal_type(frozen_set_parametrized) # revealed: frozenset - reveal_type(chain_map_bare) # revealed: ChainMap - reveal_type(chain_map_parametrized) # revealed: ChainMap + reveal_type(chain_map_bare) # revealed: ChainMap + reveal_type(chain_map_parametrized) # revealed: ChainMap - reveal_type(counter_bare) # revealed: Counter - reveal_type(counter_parametrized) # revealed: Counter + reveal_type(counter_bare) # revealed: Counter + reveal_type(counter_parametrized) # revealed: Counter - reveal_type(default_dict_bare) # revealed: defaultdict - reveal_type(default_dict_parametrized) # revealed: defaultdict + reveal_type(default_dict_bare) # revealed: defaultdict + reveal_type(default_dict_parametrized) # revealed: defaultdict - reveal_type(deque_bare) # revealed: deque - reveal_type(deque_parametrized) # revealed: deque + reveal_type(deque_bare) # revealed: deque + reveal_type(deque_parametrized) # revealed: deque - reveal_type(ordered_dict_bare) # revealed: OrderedDict - reveal_type(ordered_dict_parametrized) # revealed: OrderedDict + reveal_type(ordered_dict_bare) # revealed: OrderedDict + reveal_type(ordered_dict_parametrized) # revealed: OrderedDict ``` ## Inheritance @@ -93,26 +93,31 @@ reveal_type(_FrozenSet.__mro__) # revealed: tuple[Literal[_FrozenSet], Literal[ class _ChainMap(typing.ChainMap): ... -# revealed: tuple[Literal[_ChainMap], @Todo(Support for more typing aliases as base classes), Literal[object]] +# TODO: Should be (_ChainMap, ChainMap, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object) +# revealed: tuple[Literal[_ChainMap], Literal[ChainMap], Unknown, Literal[object]] reveal_type(_ChainMap.__mro__) class _Counter(typing.Counter): ... -# revealed: tuple[Literal[_Counter], @Todo(Support for more typing aliases as base classes), Literal[object]] +# TODO: Should be (_Counter, Counter, dict, Generic, object) +# revealed: tuple[Literal[_Counter], Literal[Counter], Unknown, Literal[object]] reveal_type(_Counter.__mro__) class _DefaultDict(typing.DefaultDict): ... -# revealed: tuple[Literal[_DefaultDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +# TODO: Should be (_DefaultDict, defaultdict, dict, Generic, object) +# revealed: tuple[Literal[_DefaultDict], Literal[defaultdict], Unknown, Literal[object]] reveal_type(_DefaultDict.__mro__) class _Deque(typing.Deque): ... -# revealed: tuple[Literal[_Deque], @Todo(Support for more typing aliases as base classes), Literal[object]] +# TODO: Should be (_Deque, deque, Generic, object) +# revealed: tuple[Literal[_Deque], Literal[deque], Unknown, Literal[object]] reveal_type(_Deque.__mro__) class _OrderedDict(typing.OrderedDict): ... -# revealed: tuple[Literal[_OrderedDict], @Todo(Support for more typing aliases as base classes), Literal[object]] +# TODO: Should be (_OrderedDict, OrderedDict, dict, Generic, object) +# revealed: tuple[Literal[_OrderedDict], Literal[OrderedDict], Unknown, Literal[object]] reveal_type(_OrderedDict.__mro__) ``` diff --git a/crates/red_knot_python_semantic/src/types/class_base.rs b/crates/red_knot_python_semantic/src/types/class_base.rs index 850b1996e85ab..169c7482c04be 100644 --- a/crates/red_knot_python_semantic/src/types/class_base.rs +++ b/crates/red_knot_python_semantic/src/types/class_base.rs @@ -112,12 +112,22 @@ impl<'db> ClassBase<'db> { KnownInstanceType::FrozenSet => { Self::try_from_ty(db, KnownClass::FrozenSet.to_class_literal(db)) } - KnownInstanceType::Callable - | KnownInstanceType::ChainMap - | KnownInstanceType::Counter - | KnownInstanceType::DefaultDict - | KnownInstanceType::Deque - | KnownInstanceType::OrderedDict => Self::try_from_ty( + KnownInstanceType::ChainMap => { + Self::try_from_ty(db, KnownClass::ChainMap.to_class_literal(db)) + } + KnownInstanceType::Counter => { + Self::try_from_ty(db, KnownClass::Counter.to_class_literal(db)) + } + KnownInstanceType::DefaultDict => { + Self::try_from_ty(db, KnownClass::DefaultDict.to_class_literal(db)) + } + KnownInstanceType::Deque => { + Self::try_from_ty(db, KnownClass::Deque.to_class_literal(db)) + } + KnownInstanceType::OrderedDict => { + Self::try_from_ty(db, KnownClass::OrderedDict.to_class_literal(db)) + } + KnownInstanceType::Callable => Self::try_from_ty( db, todo_type!("Support for more typing aliases as base classes"), ), From cec02fe0a1ca556ec40fa5a22b4c267e1f41f781 Mon Sep 17 00:00:00 2001 From: InSyncWithFoo Date: Mon, 16 Dec 2024 17:57:33 +0000 Subject: [PATCH 6/8] Per review --- .../annotations/stdlib_typing_aliases.md | 128 +++++++++--------- .../annotations/unsupported_special_forms.md | 2 +- .../src/types/class_base.rs | 7 +- 3 files changed, 68 insertions(+), 69 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index a5505e6c95269..035b1e4195630 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -11,51 +11,51 @@ All of the following symbols can be mapped one-to-one with the actual type: import typing def f( - list_bare: typing.List, - list_parametrized: typing.List[int], - dict_bare: typing.Dict, - dict_parametrized: typing.Dict[int, str], - set_bare: typing.Set, - set_parametrized: typing.Set[int], - frozen_set_bare: typing.FrozenSet, - frozen_set_parametrized: typing.FrozenSet[str], - chain_map_bare: typing.ChainMap, - chain_map_parametrized: typing.ChainMap[int], - counter_bare: typing.Counter, - counter_parametrized: typing.Counter[int], - default_dict_bare: typing.DefaultDict, - default_dict_parametrized: typing.DefaultDict[str, int], - deque_bare: typing.Deque, - deque_parametrized: typing.Deque[str], - ordered_dict_bare: typing.OrderedDict, - ordered_dict_parametrized: typing.OrderedDict[int, str], + list_bare: typing.List, + list_parametrized: typing.List[int], + dict_bare: typing.Dict, + dict_parametrized: typing.Dict[int, str], + set_bare: typing.Set, + set_parametrized: typing.Set[int], + frozen_set_bare: typing.FrozenSet, + frozen_set_parametrized: typing.FrozenSet[str], + chain_map_bare: typing.ChainMap, + chain_map_parametrized: typing.ChainMap[int], + counter_bare: typing.Counter, + counter_parametrized: typing.Counter[int], + default_dict_bare: typing.DefaultDict, + default_dict_parametrized: typing.DefaultDict[str, int], + deque_bare: typing.Deque, + deque_parametrized: typing.Deque[str], + ordered_dict_bare: typing.OrderedDict, + ordered_dict_parametrized: typing.OrderedDict[int, str], ): - reveal_type(list_bare) # revealed: list - reveal_type(list_parametrized) # revealed: list + reveal_type(list_bare) # revealed: list + reveal_type(list_parametrized) # revealed: list - reveal_type(dict_bare) # revealed: dict - reveal_type(dict_parametrized) # revealed: dict + reveal_type(dict_bare) # revealed: dict + reveal_type(dict_parametrized) # revealed: dict - reveal_type(set_bare) # revealed: set - reveal_type(set_parametrized) # revealed: set + reveal_type(set_bare) # revealed: set + reveal_type(set_parametrized) # revealed: set - reveal_type(frozen_set_bare) # revealed: frozenset - reveal_type(frozen_set_parametrized) # revealed: frozenset + reveal_type(frozen_set_bare) # revealed: frozenset + reveal_type(frozen_set_parametrized) # revealed: frozenset - reveal_type(chain_map_bare) # revealed: ChainMap - reveal_type(chain_map_parametrized) # revealed: ChainMap + reveal_type(chain_map_bare) # revealed: ChainMap + reveal_type(chain_map_parametrized) # revealed: ChainMap - reveal_type(counter_bare) # revealed: Counter - reveal_type(counter_parametrized) # revealed: Counter + reveal_type(counter_bare) # revealed: Counter + reveal_type(counter_parametrized) # revealed: Counter - reveal_type(default_dict_bare) # revealed: defaultdict - reveal_type(default_dict_parametrized) # revealed: defaultdict + reveal_type(default_dict_bare) # revealed: defaultdict + reveal_type(default_dict_parametrized) # revealed: defaultdict - reveal_type(deque_bare) # revealed: deque - reveal_type(deque_parametrized) # revealed: deque + reveal_type(deque_bare) # revealed: deque + reveal_type(deque_parametrized) # revealed: deque - reveal_type(ordered_dict_bare) # revealed: OrderedDict - reveal_type(ordered_dict_parametrized) # revealed: OrderedDict + reveal_type(ordered_dict_bare) # revealed: OrderedDict + reveal_type(ordered_dict_parametrized) # revealed: OrderedDict ``` ## Inheritance @@ -68,56 +68,56 @@ import typing #################### ### Built-ins -class _List(typing.List): ... +class ListSubclass(typing.List): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(_List.__mro__) # revealed: tuple[Literal[_List], Literal[list], Unknown, Literal[object]] +reveal_type(ListSubclass.__mro__) # revealed: tuple[Literal[ListSubclass], Literal[list], Unknown, Literal[object]] -class _Dict(typing.Dict): ... +class DictSubclass(typing.Dict): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(_Dict.__mro__) # revealed: tuple[Literal[_Dict], Literal[dict], Unknown, Literal[object]] +reveal_type(DictSubclass.__mro__) # revealed: tuple[Literal[DictSubclass], Literal[dict], Unknown, Literal[object]] -class _Set(typing.Set): ... +class SetSubclass(typing.Set): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(_Set.__mro__) # revealed: tuple[Literal[_Set], Literal[set], Unknown, Literal[object]] +reveal_type(SetSubclass.__mro__) # revealed: tuple[Literal[SetSubclass], Literal[set], Unknown, Literal[object]] -class _FrozenSet(typing.FrozenSet): ... +class FrozenSetSubclass(typing.FrozenSet): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(_FrozenSet.__mro__) # revealed: tuple[Literal[_FrozenSet], Literal[frozenset], Unknown, Literal[object]] +reveal_type(FrozenSetSubclass.__mro__) # revealed: tuple[Literal[FrozenSetSubclass], Literal[frozenset], Unknown, Literal[object]] #################### ### `collections` -class _ChainMap(typing.ChainMap): ... +class ChainMapSubclass(typing.ChainMap): ... -# TODO: Should be (_ChainMap, ChainMap, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object) -# revealed: tuple[Literal[_ChainMap], Literal[ChainMap], Unknown, Literal[object]] -reveal_type(_ChainMap.__mro__) +# TODO: Should be (ChainMapSubclass, ChainMap, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object) +# revealed: tuple[Literal[ChainMapSubclass], Literal[ChainMap], Unknown, Literal[object]] +reveal_type(ChainMapSubclass.__mro__) -class _Counter(typing.Counter): ... +class CounterSubclass(typing.Counter): ... -# TODO: Should be (_Counter, Counter, dict, Generic, object) -# revealed: tuple[Literal[_Counter], Literal[Counter], Unknown, Literal[object]] -reveal_type(_Counter.__mro__) +# TODO: Should be (CounterSubclass, Counter, dict, Generic, object) +# revealed: tuple[Literal[CounterSubclass], Literal[Counter], Unknown, Literal[object]] +reveal_type(CounterSubclass.__mro__) -class _DefaultDict(typing.DefaultDict): ... +class DefaultDictSubclass(typing.DefaultDict): ... -# TODO: Should be (_DefaultDict, defaultdict, dict, Generic, object) -# revealed: tuple[Literal[_DefaultDict], Literal[defaultdict], Unknown, Literal[object]] -reveal_type(_DefaultDict.__mro__) +# TODO: Should be (DefaultDictSubclass, defaultdict, dict, Generic, object) +# revealed: tuple[Literal[DefaultDictSubclass], Literal[defaultdict], Unknown, Literal[object]] +reveal_type(DefaultDictSubclass.__mro__) -class _Deque(typing.Deque): ... +class DequeSubclass(typing.Deque): ... -# TODO: Should be (_Deque, deque, Generic, object) -# revealed: tuple[Literal[_Deque], Literal[deque], Unknown, Literal[object]] -reveal_type(_Deque.__mro__) +# TODO: Should be (DequeSubclass, deque, Generic, object) +# revealed: tuple[Literal[DequeSubclass], Literal[deque], Unknown, Literal[object]] +reveal_type(DequeSubclass.__mro__) -class _OrderedDict(typing.OrderedDict): ... +class OrderedDictSubclass(typing.OrderedDict): ... -# TODO: Should be (_OrderedDict, OrderedDict, dict, Generic, object) -# revealed: tuple[Literal[_OrderedDict], Literal[OrderedDict], Unknown, Literal[object]] -reveal_type(_OrderedDict.__mro__) +# TODO: Should be (OrderedDictSubclass, OrderedDict, dict, Generic, object) +# revealed: tuple[Literal[OrderedDictSubclass], Literal[OrderedDict], Unknown, Literal[object]] +reveal_type(OrderedDictSubclass.__mro__) ``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md index 6b56df44b2073..37d9dfb7d43c3 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md @@ -51,7 +51,7 @@ class D(TypeIs): ... # error: [invalid-base] class E(Concatenate): ... # error: [invalid-base] class F(Callable): ... -reveal_type(F.__mro__) # revealed: tuple[Literal[F], @Todo(Support for more typing aliases as base classes), Literal[object]] +reveal_type(F.__mro__) # revealed: tuple[Literal[F], @Todo(Support for Callable as a base class), Literal[object]] ``` ## Subscriptability diff --git a/crates/red_knot_python_semantic/src/types/class_base.rs b/crates/red_knot_python_semantic/src/types/class_base.rs index 169c7482c04be..ede1e5e1c91b3 100644 --- a/crates/red_knot_python_semantic/src/types/class_base.rs +++ b/crates/red_knot_python_semantic/src/types/class_base.rs @@ -127,10 +127,9 @@ impl<'db> ClassBase<'db> { KnownInstanceType::OrderedDict => { Self::try_from_ty(db, KnownClass::OrderedDict.to_class_literal(db)) } - KnownInstanceType::Callable => Self::try_from_ty( - db, - todo_type!("Support for more typing aliases as base classes"), - ), + KnownInstanceType::Callable => { + Self::try_from_ty(db, todo_type!("Support for Callable as a base class")) + } }, } } From 0eddc094bb1d14b09a3167773420ce675444d2b0 Mon Sep 17 00:00:00 2001 From: InSync Date: Tue, 17 Dec 2024 01:03:42 +0700 Subject: [PATCH 7/8] Formatting --- .../mdtest/annotations/stdlib_typing_aliases.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index 035b1e4195630..87c160dbfd29b 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -71,22 +71,26 @@ import typing class ListSubclass(typing.List): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(ListSubclass.__mro__) # revealed: tuple[Literal[ListSubclass], Literal[list], Unknown, Literal[object]] +# revealed: tuple[Literal[ListSubclass], Literal[list], Unknown, Literal[object]] +reveal_type(ListSubclass.__mro__) class DictSubclass(typing.Dict): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(DictSubclass.__mro__) # revealed: tuple[Literal[DictSubclass], Literal[dict], Unknown, Literal[object]] +# revealed: tuple[Literal[DictSubclass], Literal[dict], Unknown, Literal[object]] +reveal_type(DictSubclass.__mro__) class SetSubclass(typing.Set): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(SetSubclass.__mro__) # revealed: tuple[Literal[SetSubclass], Literal[set], Unknown, Literal[object]] +# revealed: tuple[Literal[SetSubclass], Literal[set], Unknown, Literal[object]] +reveal_type(SetSubclass.__mro__) class FrozenSetSubclass(typing.FrozenSet): ... # TODO: should have `Generic`, should not have `Unknown` -reveal_type(FrozenSetSubclass.__mro__) # revealed: tuple[Literal[FrozenSetSubclass], Literal[frozenset], Unknown, Literal[object]] +# revealed: tuple[Literal[FrozenSetSubclass], Literal[frozenset], Unknown, Literal[object]] +reveal_type(FrozenSetSubclass.__mro__) #################### ### `collections` From f398f1f216ec3458aac68076e91ef16c9b0f60b1 Mon Sep 17 00:00:00 2001 From: InSyncWithFoo Date: Tue, 17 Dec 2024 09:01:25 +0000 Subject: [PATCH 8/8] Per review --- .../resources/mdtest/annotations/stdlib_typing_aliases.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md index 87c160dbfd29b..057efca54cce4 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md +++ b/crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md @@ -103,25 +103,25 @@ reveal_type(ChainMapSubclass.__mro__) class CounterSubclass(typing.Counter): ... -# TODO: Should be (CounterSubclass, Counter, dict, Generic, object) +# TODO: Should be (CounterSubclass, Counter, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object) # revealed: tuple[Literal[CounterSubclass], Literal[Counter], Unknown, Literal[object]] reveal_type(CounterSubclass.__mro__) class DefaultDictSubclass(typing.DefaultDict): ... -# TODO: Should be (DefaultDictSubclass, defaultdict, dict, Generic, object) +# TODO: Should be (DefaultDictSubclass, defaultdict, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object) # revealed: tuple[Literal[DefaultDictSubclass], Literal[defaultdict], Unknown, Literal[object]] reveal_type(DefaultDictSubclass.__mro__) class DequeSubclass(typing.Deque): ... -# TODO: Should be (DequeSubclass, deque, Generic, object) +# TODO: Should be (DequeSubclass, deque, MutableSequence, Sequence, Reversible, Collection, Sized, Iterable, Container, Generic, object) # revealed: tuple[Literal[DequeSubclass], Literal[deque], Unknown, Literal[object]] reveal_type(DequeSubclass.__mro__) class OrderedDictSubclass(typing.OrderedDict): ... -# TODO: Should be (OrderedDictSubclass, OrderedDict, dict, Generic, object) +# TODO: Should be (OrderedDictSubclass, OrderedDict, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object) # revealed: tuple[Literal[OrderedDictSubclass], Literal[OrderedDict], Unknown, Literal[object]] reveal_type(OrderedDictSubclass.__mro__) ```