mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
[red-knot] Add explicit TODO branches for many typing special forms and qualifiers (#14936)
This commit is contained in:
parent
58930905eb
commit
71239f248e
6 changed files with 471 additions and 22 deletions
|
@ -0,0 +1,83 @@
|
|||
# Typing-module aliases to other stdlib classes
|
||||
|
||||
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
|
||||
|
||||
Support for most of these symbols is currently a TODO:
|
||||
|
||||
```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],
|
||||
):
|
||||
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)
|
||||
```
|
||||
|
||||
## Inheritance
|
||||
|
||||
The aliases can be inherited from. Some of these are still partially or wholly TODOs.
|
||||
|
||||
```py
|
||||
import typing
|
||||
|
||||
class A(typing.Dict): ...
|
||||
|
||||
# TODO: should have `Generic`, should not have `Unknown`
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[dict], Unknown, Literal[object]]
|
||||
|
||||
class B(typing.List): ...
|
||||
|
||||
# TODO: should have `Generic`, should not have `Unknown`
|
||||
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[list], Unknown, Literal[object]]
|
||||
|
||||
class C(typing.Set): ...
|
||||
|
||||
# TODO: should have `Generic`, should not have `Unknown`
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[set], Unknown, Literal[object]]
|
||||
|
||||
class D(typing.FrozenSet): ...
|
||||
|
||||
# TODO: should have `Generic`, should not have `Unknown`
|
||||
reveal_type(D.__mro__) # revealed: tuple[Literal[D], Literal[frozenset], Unknown, Literal[object]]
|
||||
|
||||
class E(typing.DefaultDict): ...
|
||||
|
||||
reveal_type(E.__mro__) # revealed: tuple[Literal[E], @Todo(Support for more typing aliases as base classes), Literal[object]]
|
||||
|
||||
class F(typing.OrderedDict): ...
|
||||
|
||||
reveal_type(F.__mro__) # revealed: tuple[Literal[F], @Todo(Support for more typing aliases as base classes), Literal[object]]
|
||||
|
||||
class G(typing.Counter): ...
|
||||
|
||||
reveal_type(G.__mro__) # revealed: tuple[Literal[G], @Todo(Support for more typing aliases as base classes), Literal[object]]
|
||||
```
|
|
@ -0,0 +1,71 @@
|
|||
# Unsupported special forms
|
||||
|
||||
## Not yet supported
|
||||
|
||||
Several special forms are unsupported by red-knot currently. However, we also don't emit
|
||||
false-positive errors if you use one in an annotation:
|
||||
|
||||
```py
|
||||
from typing_extensions import Self, TypeVarTuple, Unpack, TypeGuard, TypeIs, Concatenate, ParamSpec, TypeAlias, Callable, TypeVar
|
||||
|
||||
P = ParamSpec("P")
|
||||
Ts = TypeVarTuple("Ts")
|
||||
R_co = TypeVar("R_co", covariant=True)
|
||||
|
||||
Alias: TypeAlias = int
|
||||
|
||||
def f(*args: Unpack[Ts]) -> tuple[Unpack[Ts]]:
|
||||
# TODO: should understand the annotation
|
||||
reveal_type(args) # revealed: tuple
|
||||
|
||||
reveal_type(Alias) # revealed: @Todo(Unsupported or invalid type in a type expression)
|
||||
|
||||
def g() -> TypeGuard[int]: ...
|
||||
def h() -> TypeIs[int]: ...
|
||||
def i(callback: Callable[Concatenate[int, P], R_co], *args: P.args, **kwargs: P.kwargs) -> R_co:
|
||||
# TODO: should understand the annotation
|
||||
reveal_type(args) # revealed: tuple
|
||||
|
||||
# TODO: should understand the annotation
|
||||
reveal_type(kwargs) # revealed: dict
|
||||
|
||||
return callback(42, *args, **kwargs)
|
||||
|
||||
class Foo:
|
||||
def method(self, x: Self):
|
||||
reveal_type(x) # revealed: @Todo(Unsupported or invalid type in a type expression)
|
||||
```
|
||||
|
||||
## Inheritance
|
||||
|
||||
You can't inherit from most of these. `typing.Callable` is an exception.
|
||||
|
||||
```py
|
||||
from typing import Callable
|
||||
from typing_extensions import Self, Unpack, TypeGuard, TypeIs, Concatenate
|
||||
|
||||
class A(Self): ... # error: [invalid-base]
|
||||
class B(Unpack): ... # error: [invalid-base]
|
||||
class C(TypeGuard): ... # error: [invalid-base]
|
||||
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]]
|
||||
```
|
||||
|
||||
## Subscriptability
|
||||
|
||||
Some of these are not subscriptable:
|
||||
|
||||
```py
|
||||
from typing_extensions import Self, TypeAlias
|
||||
|
||||
X: TypeAlias[T] = int # error: [invalid-type-parameter]
|
||||
|
||||
class Foo[T]:
|
||||
# error: [invalid-type-parameter] "Special form `typing.Self` expected no type parameter"
|
||||
# error: [invalid-type-parameter] "Special form `typing.Self` expected no type parameter"
|
||||
def method(self: Self[int]) -> Self[int]:
|
||||
reveal_type(self) # revealed: Unknown
|
||||
```
|
|
@ -0,0 +1,37 @@
|
|||
# Unsupported type qualifiers
|
||||
|
||||
## Not yet supported
|
||||
|
||||
Several type qualifiers are unsupported by red-knot currently. However, we also don't emit
|
||||
false-positive errors if you use one in an annotation:
|
||||
|
||||
```py
|
||||
from typing_extensions import Final, ClassVar, Required, NotRequired, ReadOnly, TypedDict
|
||||
|
||||
X: Final = 42
|
||||
Y: Final[int] = 42
|
||||
|
||||
class Foo:
|
||||
A: ClassVar[int] = 42
|
||||
|
||||
# TODO: `TypedDict` is actually valid as a base
|
||||
# error: [invalid-base]
|
||||
class Bar(TypedDict):
|
||||
x: Required[int]
|
||||
y: NotRequired[str]
|
||||
z: ReadOnly[bytes]
|
||||
```
|
||||
|
||||
## Inheritance
|
||||
|
||||
You can't inherit from a type qualifier.
|
||||
|
||||
```py
|
||||
from typing_extensions import Final, ClassVar, Required, NotRequired, ReadOnly
|
||||
|
||||
class A(Final): ... # error: [invalid-base]
|
||||
class B(ClassVar): ... # error: [invalid-base]
|
||||
class C(Required): ... # error: [invalid-base]
|
||||
class D(NotRequired): ... # error: [invalid-base]
|
||||
class E(ReadOnly): ... # error: [invalid-base]
|
||||
```
|
|
@ -1255,6 +1255,7 @@ impl<'db> Type<'db> {
|
|||
| KnownClass::List
|
||||
| KnownClass::Tuple
|
||||
| KnownClass::Set
|
||||
| KnownClass::FrozenSet
|
||||
| KnownClass::Dict
|
||||
| KnownClass::Slice
|
||||
| KnownClass::BaseException
|
||||
|
@ -1263,6 +1264,7 @@ impl<'db> Type<'db> {
|
|||
| KnownClass::ModuleType
|
||||
| KnownClass::FunctionType
|
||||
| KnownClass::SpecialForm
|
||||
| KnownClass::StdlibAlias
|
||||
| KnownClass::TypeVar,
|
||||
) => false,
|
||||
None => false,
|
||||
|
@ -1782,7 +1784,8 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
Type::KnownInstance(KnownInstanceType::LiteralString) => Type::LiteralString,
|
||||
Type::KnownInstance(KnownInstanceType::Any) => Type::Any,
|
||||
_ => todo_type!(),
|
||||
Type::Todo(_) => *self,
|
||||
_ => todo_type!("Unsupported or invalid type in a type expression"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1934,6 +1937,7 @@ pub enum KnownClass {
|
|||
List,
|
||||
Tuple,
|
||||
Set,
|
||||
FrozenSet,
|
||||
Dict,
|
||||
Slice,
|
||||
BaseException,
|
||||
|
@ -1945,6 +1949,7 @@ pub enum KnownClass {
|
|||
// Typeshed
|
||||
NoneType, // Part of `types` for Python >= 3.10
|
||||
// Typing
|
||||
StdlibAlias,
|
||||
SpecialForm,
|
||||
TypeVar,
|
||||
TypeAliasType,
|
||||
|
@ -1962,6 +1967,7 @@ impl<'db> KnownClass {
|
|||
Self::Tuple => "tuple",
|
||||
Self::Int => "int",
|
||||
Self::Float => "float",
|
||||
Self::FrozenSet => "frozenset",
|
||||
Self::Str => "str",
|
||||
Self::Set => "set",
|
||||
Self::Dict => "dict",
|
||||
|
@ -1978,6 +1984,8 @@ impl<'db> KnownClass {
|
|||
Self::TypeVar => "TypeVar",
|
||||
Self::TypeAliasType => "TypeAliasType",
|
||||
Self::NoDefaultType => "_NoDefaultType",
|
||||
// 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,
|
||||
// which is different to what `type(sys.version_info).__name__` is at runtime.
|
||||
// (At runtime, `type(sys.version_info).__name__ == "version_info"`,
|
||||
|
@ -2016,6 +2024,7 @@ impl<'db> KnownClass {
|
|||
| Self::List
|
||||
| Self::Tuple
|
||||
| Self::Set
|
||||
| Self::FrozenSet
|
||||
| Self::Dict
|
||||
| Self::BaseException
|
||||
| Self::BaseExceptionGroup
|
||||
|
@ -2023,7 +2032,9 @@ impl<'db> KnownClass {
|
|||
Self::VersionInfo => CoreStdlibModule::Sys,
|
||||
Self::GenericAlias | Self::ModuleType | Self::FunctionType => CoreStdlibModule::Types,
|
||||
Self::NoneType => CoreStdlibModule::Typeshed,
|
||||
Self::SpecialForm | Self::TypeVar | Self::TypeAliasType => CoreStdlibModule::Typing,
|
||||
Self::SpecialForm | Self::TypeVar | Self::TypeAliasType | Self::StdlibAlias => {
|
||||
CoreStdlibModule::Typing
|
||||
}
|
||||
Self::NoDefaultType => {
|
||||
let python_version = Program::get(db).target_version(db);
|
||||
|
||||
|
@ -2054,6 +2065,7 @@ impl<'db> KnownClass {
|
|||
| Self::Float
|
||||
| Self::Str
|
||||
| Self::Set
|
||||
| Self::FrozenSet
|
||||
| Self::Dict
|
||||
| Self::List
|
||||
| Self::Type
|
||||
|
@ -2062,6 +2074,7 @@ impl<'db> KnownClass {
|
|||
| Self::ModuleType
|
||||
| Self::FunctionType
|
||||
| Self::SpecialForm
|
||||
| Self::StdlibAlias
|
||||
| Self::BaseException
|
||||
| Self::BaseExceptionGroup
|
||||
| Self::TypeVar => false,
|
||||
|
@ -2082,6 +2095,7 @@ impl<'db> KnownClass {
|
|||
"float" => Self::Float,
|
||||
"str" => Self::Str,
|
||||
"set" => Self::Set,
|
||||
"frozenset" => Self::FrozenSet,
|
||||
"dict" => Self::Dict,
|
||||
"list" => Self::List,
|
||||
"slice" => Self::Slice,
|
||||
|
@ -2092,6 +2106,7 @@ impl<'db> KnownClass {
|
|||
"ModuleType" => Self::ModuleType,
|
||||
"FunctionType" => Self::FunctionType,
|
||||
"TypeAliasType" => Self::TypeAliasType,
|
||||
"_Alias" => Self::StdlibAlias,
|
||||
"_SpecialForm" => Self::SpecialForm,
|
||||
"_NoDefaultType" => Self::NoDefaultType,
|
||||
"_version_info" => Self::VersionInfo,
|
||||
|
@ -2118,9 +2133,11 @@ impl<'db> KnownClass {
|
|||
| Self::List
|
||||
| Self::Tuple
|
||||
| Self::Set
|
||||
| Self::FrozenSet
|
||||
| Self::Dict
|
||||
| Self::Slice
|
||||
| Self::GenericAlias
|
||||
| Self::StdlibAlias // no equivalent class exists in typing_extensions, nor ever will
|
||||
| Self::ModuleType
|
||||
| Self::VersionInfo
|
||||
| Self::BaseException
|
||||
|
@ -2159,6 +2176,30 @@ pub enum KnownInstanceType<'db> {
|
|||
TypeVar(TypeVarInstance<'db>),
|
||||
/// A single instance of `typing.TypeAliasType` (PEP 695 type alias)
|
||||
TypeAliasType(TypeAliasType<'db>),
|
||||
|
||||
// Various special forms, special aliases and type qualifiers that we don't yet understand
|
||||
// (all currently inferred as TODO in most contexts):
|
||||
TypingSelf,
|
||||
Final,
|
||||
ClassVar,
|
||||
Callable,
|
||||
Concatenate,
|
||||
Unpack,
|
||||
Required,
|
||||
NotRequired,
|
||||
TypeAlias,
|
||||
TypeGuard,
|
||||
TypeIs,
|
||||
List,
|
||||
Dict,
|
||||
DefaultDict,
|
||||
Set,
|
||||
FrozenSet,
|
||||
Counter,
|
||||
Deque,
|
||||
ChainMap,
|
||||
OrderedDict,
|
||||
ReadOnly,
|
||||
// TODO: fill this enum out with more special forms, etc.
|
||||
}
|
||||
|
||||
|
@ -2176,6 +2217,27 @@ impl<'db> KnownInstanceType<'db> {
|
|||
Self::Tuple => "Tuple",
|
||||
Self::Type => "Type",
|
||||
Self::TypeAliasType(_) => "TypeAliasType",
|
||||
Self::TypingSelf => "Self",
|
||||
Self::Final => "Final",
|
||||
Self::ClassVar => "ClassVar",
|
||||
Self::Callable => "Callable",
|
||||
Self::Concatenate => "Concatenate",
|
||||
Self::Unpack => "Unpack",
|
||||
Self::Required => "Required",
|
||||
Self::NotRequired => "NotRequired",
|
||||
Self::TypeAlias => "TypeAlias",
|
||||
Self::TypeGuard => "TypeGuard",
|
||||
Self::TypeIs => "TypeIs",
|
||||
Self::List => "List",
|
||||
Self::Dict => "Dict",
|
||||
Self::DefaultDict => "DefaultDict",
|
||||
Self::Set => "Set",
|
||||
Self::FrozenSet => "FrozenSet",
|
||||
Self::Counter => "Counter",
|
||||
Self::Deque => "Deque",
|
||||
Self::ChainMap => "ChainMap",
|
||||
Self::OrderedDict => "OrderedDict",
|
||||
Self::ReadOnly => "ReadOnly",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2192,6 +2254,27 @@ impl<'db> KnownInstanceType<'db> {
|
|||
| Self::Any
|
||||
| Self::Tuple
|
||||
| Self::Type
|
||||
| Self::TypingSelf
|
||||
| Self::Final
|
||||
| Self::ClassVar
|
||||
| Self::Callable
|
||||
| Self::Concatenate
|
||||
| Self::Unpack
|
||||
| Self::Required
|
||||
| Self::NotRequired
|
||||
| Self::TypeAlias
|
||||
| Self::TypeGuard
|
||||
| Self::TypeIs
|
||||
| Self::List
|
||||
| Self::Dict
|
||||
| Self::DefaultDict
|
||||
| Self::Set
|
||||
| Self::FrozenSet
|
||||
| Self::Counter
|
||||
| Self::Deque
|
||||
| Self::ChainMap
|
||||
| Self::OrderedDict
|
||||
| Self::ReadOnly
|
||||
| Self::TypeAliasType(_) => Truthiness::AlwaysTrue,
|
||||
}
|
||||
}
|
||||
|
@ -2208,6 +2291,27 @@ impl<'db> KnownInstanceType<'db> {
|
|||
Self::Any => "typing.Any",
|
||||
Self::Tuple => "typing.Tuple",
|
||||
Self::Type => "typing.Type",
|
||||
Self::TypingSelf => "typing.Self",
|
||||
Self::Final => "typing.Final",
|
||||
Self::ClassVar => "typing.ClassVar",
|
||||
Self::Callable => "typing.Callable",
|
||||
Self::Concatenate => "typing.Concatenate",
|
||||
Self::Unpack => "typing.Unpack",
|
||||
Self::Required => "typing.Required",
|
||||
Self::NotRequired => "typing.NotRequired",
|
||||
Self::TypeAlias => "typing.TypeAlias",
|
||||
Self::TypeGuard => "typing.TypeGuard",
|
||||
Self::TypeIs => "typing.TypeIs",
|
||||
Self::List => "typing.List",
|
||||
Self::Dict => "typing.Dict",
|
||||
Self::DefaultDict => "typing.DefaultDict",
|
||||
Self::Set => "typing.Set",
|
||||
Self::FrozenSet => "typing.FrozenSet",
|
||||
Self::Counter => "typing.Counter",
|
||||
Self::Deque => "typing.Deque",
|
||||
Self::ChainMap => "typing.ChainMap",
|
||||
Self::OrderedDict => "typing.OrderedDict",
|
||||
Self::ReadOnly => "typing.ReadOnly",
|
||||
Self::TypeVar(typevar) => typevar.name(db),
|
||||
Self::TypeAliasType(_) => "typing.TypeAliasType",
|
||||
}
|
||||
|
@ -2225,6 +2329,27 @@ impl<'db> KnownInstanceType<'db> {
|
|||
Self::Any => KnownClass::Object,
|
||||
Self::Tuple => KnownClass::SpecialForm,
|
||||
Self::Type => KnownClass::SpecialForm,
|
||||
Self::TypingSelf => KnownClass::SpecialForm,
|
||||
Self::Final => KnownClass::SpecialForm,
|
||||
Self::ClassVar => KnownClass::SpecialForm,
|
||||
Self::Callable => KnownClass::SpecialForm,
|
||||
Self::Concatenate => KnownClass::SpecialForm,
|
||||
Self::Unpack => KnownClass::SpecialForm,
|
||||
Self::Required => KnownClass::SpecialForm,
|
||||
Self::NotRequired => KnownClass::SpecialForm,
|
||||
Self::TypeAlias => KnownClass::SpecialForm,
|
||||
Self::TypeGuard => KnownClass::SpecialForm,
|
||||
Self::TypeIs => KnownClass::SpecialForm,
|
||||
Self::ReadOnly => KnownClass::SpecialForm,
|
||||
Self::List => KnownClass::StdlibAlias,
|
||||
Self::Dict => KnownClass::StdlibAlias,
|
||||
Self::DefaultDict => KnownClass::StdlibAlias,
|
||||
Self::Set => KnownClass::StdlibAlias,
|
||||
Self::FrozenSet => KnownClass::StdlibAlias,
|
||||
Self::Counter => KnownClass::StdlibAlias,
|
||||
Self::Deque => KnownClass::StdlibAlias,
|
||||
Self::ChainMap => KnownClass::StdlibAlias,
|
||||
Self::OrderedDict => KnownClass::StdlibAlias,
|
||||
Self::TypeVar(_) => KnownClass::TypeVar,
|
||||
Self::TypeAliasType(_) => KnownClass::TypeAliasType,
|
||||
}
|
||||
|
@ -2245,14 +2370,35 @@ impl<'db> KnownInstanceType<'db> {
|
|||
}
|
||||
match (module.name().as_str(), instance_name) {
|
||||
("typing", "Any") => Some(Self::Any),
|
||||
("typing", "ClassVar") => Some(Self::ClassVar),
|
||||
("typing", "Deque") => Some(Self::Deque),
|
||||
("typing", "List") => Some(Self::List),
|
||||
("typing", "Dict") => Some(Self::Dict),
|
||||
("typing", "DefaultDict") => Some(Self::DefaultDict),
|
||||
("typing", "Set") => Some(Self::Set),
|
||||
("typing", "FrozenSet") => Some(Self::FrozenSet),
|
||||
("typing", "Counter") => Some(Self::Counter),
|
||||
("typing", "ChainMap") => Some(Self::ChainMap),
|
||||
("typing", "OrderedDict") => Some(Self::OrderedDict),
|
||||
("typing", "Optional") => Some(Self::Optional),
|
||||
("typing", "Union") => Some(Self::Union),
|
||||
("typing", "NoReturn") => Some(Self::NoReturn),
|
||||
("typing", "Tuple") => Some(Self::Tuple),
|
||||
("typing", "Type") => Some(Self::Type),
|
||||
("typing", "Callable") => Some(Self::Callable),
|
||||
("typing" | "typing_extensions", "Literal") => Some(Self::Literal),
|
||||
("typing" | "typing_extensions", "LiteralString") => Some(Self::LiteralString),
|
||||
("typing" | "typing_extensions", "Optional") => Some(Self::Optional),
|
||||
("typing" | "typing_extensions", "Union") => Some(Self::Union),
|
||||
("typing" | "typing_extensions", "NoReturn") => Some(Self::NoReturn),
|
||||
("typing" | "typing_extensions", "Never") => Some(Self::Never),
|
||||
("typing" | "typing_extensions", "Tuple") => Some(Self::Tuple),
|
||||
("typing" | "typing_extensions", "Type") => Some(Self::Type),
|
||||
("typing" | "typing_extensions", "Self") => Some(Self::TypingSelf),
|
||||
("typing" | "typing_extensions", "Final") => Some(Self::Final),
|
||||
("typing" | "typing_extensions", "Concatenate") => Some(Self::Concatenate),
|
||||
("typing" | "typing_extensions", "Unpack") => Some(Self::Unpack),
|
||||
("typing" | "typing_extensions", "Required") => Some(Self::Required),
|
||||
("typing" | "typing_extensions", "NotRequired") => Some(Self::NotRequired),
|
||||
("typing" | "typing_extensions", "TypeAlias") => Some(Self::TypeAlias),
|
||||
("typing" | "typing_extensions", "TypeGuard") => Some(Self::TypeGuard),
|
||||
("typing" | "typing_extensions", "TypeIs") => Some(Self::TypeIs),
|
||||
("typing" | "typing_extensions", "ReadOnly") => Some(Self::ReadOnly),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4786,6 +4786,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
Type::KnownInstance(known_instance) => {
|
||||
self.infer_parameterized_known_instance_type_expression(subscript, known_instance)
|
||||
}
|
||||
Type::Todo(_) => {
|
||||
self.infer_type_expression(slice);
|
||||
value_ty
|
||||
}
|
||||
_ => {
|
||||
self.infer_type_expression(slice);
|
||||
todo_type!("generics")
|
||||
|
@ -4833,13 +4837,89 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
},
|
||||
KnownInstanceType::TypeVar(_) => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!()
|
||||
todo_type!("TypeVar annotations")
|
||||
}
|
||||
KnownInstanceType::TypeAliasType(_) => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("generic type alias")
|
||||
todo_type!("Generic PEP-695 type alias")
|
||||
}
|
||||
KnownInstanceType::NoReturn | KnownInstanceType::Never => {
|
||||
KnownInstanceType::Callable => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("Callable types")
|
||||
}
|
||||
KnownInstanceType::ChainMap => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.ChainMap alias")
|
||||
}
|
||||
KnownInstanceType::OrderedDict => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.OrderedDict alias")
|
||||
}
|
||||
KnownInstanceType::Dict => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.Dict alias")
|
||||
}
|
||||
KnownInstanceType::List => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.List alias")
|
||||
}
|
||||
KnownInstanceType::DefaultDict => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.DefaultDict[] alias")
|
||||
}
|
||||
KnownInstanceType::Counter => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.Counter[] alias")
|
||||
}
|
||||
KnownInstanceType::Set => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.Set alias")
|
||||
}
|
||||
KnownInstanceType::FrozenSet => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.FrozenSet alias")
|
||||
}
|
||||
KnownInstanceType::Deque => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("typing.Deque alias")
|
||||
}
|
||||
KnownInstanceType::ReadOnly => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("Required[] type qualifier")
|
||||
}
|
||||
KnownInstanceType::NotRequired => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("NotRequired[] type qualifier")
|
||||
}
|
||||
KnownInstanceType::ClassVar => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("ClassVar[] type qualifier")
|
||||
}
|
||||
KnownInstanceType::Final => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("Final[] type qualifier")
|
||||
}
|
||||
KnownInstanceType::Required => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("Required[] type qualifier")
|
||||
}
|
||||
KnownInstanceType::TypeIs => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("TypeIs[] special form")
|
||||
}
|
||||
KnownInstanceType::TypeGuard => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("TypeGuard[] special form")
|
||||
}
|
||||
KnownInstanceType::Concatenate => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("Concatenate[] special form")
|
||||
}
|
||||
KnownInstanceType::Unpack => {
|
||||
self.infer_type_expression(parameters);
|
||||
todo_type!("Unpack[] special form")
|
||||
}
|
||||
KnownInstanceType::NoReturn | KnownInstanceType::Never | KnownInstanceType::Any => {
|
||||
self.diagnostics.add_lint(
|
||||
&INVALID_TYPE_PARAMETER,
|
||||
subscript.into(),
|
||||
|
@ -4850,6 +4930,17 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
);
|
||||
Type::Unknown
|
||||
}
|
||||
KnownInstanceType::TypingSelf | KnownInstanceType::TypeAlias => {
|
||||
self.diagnostics.add_lint(
|
||||
&INVALID_TYPE_PARAMETER,
|
||||
subscript.into(),
|
||||
format_args!(
|
||||
"Special form `{}` expected no type parameter",
|
||||
known_instance.repr(self.db)
|
||||
),
|
||||
);
|
||||
Type::Unknown
|
||||
}
|
||||
KnownInstanceType::LiteralString => {
|
||||
self.diagnostics.add_lint(
|
||||
&INVALID_TYPE_PARAMETER,
|
||||
|
@ -4863,17 +4954,6 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
}
|
||||
KnownInstanceType::Type => self.infer_subclass_of_type_expression(parameters),
|
||||
KnownInstanceType::Tuple => self.infer_tuple_type_expression(parameters),
|
||||
KnownInstanceType::Any => {
|
||||
self.diagnostics.add_lint(
|
||||
&INVALID_TYPE_PARAMETER,
|
||||
subscript.into(),
|
||||
format_args!(
|
||||
"Type `{}` expected no type parameter",
|
||||
known_instance.repr(self.db)
|
||||
),
|
||||
);
|
||||
Type::Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::ops::Deref;
|
|||
use itertools::Either;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use super::{Class, ClassLiteralType, KnownClass, KnownInstanceType, TodoType, Type};
|
||||
use super::{todo_type, Class, ClassLiteralType, KnownClass, KnownInstanceType, TodoType, Type};
|
||||
use crate::Db;
|
||||
|
||||
/// The inferred method resolution order of a given class.
|
||||
|
@ -362,15 +362,47 @@ impl<'db> ClassBase<'db> {
|
|||
| KnownInstanceType::Union
|
||||
| KnownInstanceType::NoReturn
|
||||
| KnownInstanceType::Never
|
||||
| KnownInstanceType::Final
|
||||
| KnownInstanceType::NotRequired
|
||||
| KnownInstanceType::TypeGuard
|
||||
| KnownInstanceType::TypeIs
|
||||
| KnownInstanceType::TypingSelf
|
||||
| KnownInstanceType::Unpack
|
||||
| KnownInstanceType::ClassVar
|
||||
| KnownInstanceType::Concatenate
|
||||
| KnownInstanceType::Required
|
||||
| KnownInstanceType::TypeAlias
|
||||
| KnownInstanceType::ReadOnly
|
||||
| KnownInstanceType::Optional => None,
|
||||
KnownInstanceType::Any => Some(Self::Any),
|
||||
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO
|
||||
KnownInstanceType::Dict => {
|
||||
ClassBase::try_from_ty(db, KnownClass::Dict.to_class_literal(db))
|
||||
}
|
||||
KnownInstanceType::List => {
|
||||
ClassBase::try_from_ty(db, KnownClass::List.to_class_literal(db))
|
||||
}
|
||||
KnownInstanceType::Type => {
|
||||
ClassBase::try_from_ty(db, KnownClass::Type.to_class_literal(db))
|
||||
}
|
||||
KnownInstanceType::Tuple => {
|
||||
ClassBase::try_from_ty(db, KnownClass::Tuple.to_class_literal(db))
|
||||
}
|
||||
KnownInstanceType::Set => {
|
||||
ClassBase::try_from_ty(db, KnownClass::Set.to_class_literal(db))
|
||||
}
|
||||
KnownInstanceType::FrozenSet => {
|
||||
ClassBase::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(
|
||||
db,
|
||||
todo_type!("Support for more typing aliases as base classes"),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue