Patch is_assignable_to to add partial support for SupportsIndex
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# Protocols
|
||||
|
||||
We do not support protocols yet, but to avoid false positives, we *partially* support some known
|
||||
protocols.
|
||||
|
||||
## `typing.SupportsIndex`
|
||||
|
||||
```py
|
||||
from typing import SupportsIndex, Literal
|
||||
|
||||
def _(some_int: int, some_literal_int: Literal[1], some_indexable: SupportsIndex):
|
||||
a: SupportsIndex = some_int
|
||||
b: SupportsIndex = some_literal_int
|
||||
c: SupportsIndex = some_indexable
|
||||
```
|
||||
@@ -812,6 +812,25 @@ impl<'db> Type<'db> {
|
||||
true
|
||||
}
|
||||
|
||||
// TODO: This is a workaround to avoid false positives (e.g. when checking function calls
|
||||
// with `SupportsIndex` parameters), which should be removed when we understand protocols.
|
||||
(lhs, Type::Instance(InstanceType { class }))
|
||||
if class.is_known(db, KnownClass::SupportsIndex) =>
|
||||
{
|
||||
match lhs {
|
||||
Type::Instance(InstanceType { class })
|
||||
if matches!(
|
||||
class.known(db),
|
||||
Some(KnownClass::Int | KnownClass::SupportsIndex)
|
||||
) =>
|
||||
{
|
||||
true
|
||||
}
|
||||
Type::IntLiteral(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO other types containing gradual forms (e.g. generics containing Any/Unknown)
|
||||
_ => self.is_subtype_of(db, target),
|
||||
}
|
||||
@@ -1370,6 +1389,7 @@ impl<'db> Type<'db> {
|
||||
| KnownClass::DefaultDict
|
||||
| KnownClass::Deque
|
||||
| KnownClass::OrderedDict
|
||||
| KnownClass::SupportsIndex
|
||||
| KnownClass::StdlibAlias
|
||||
| KnownClass::TypeVar,
|
||||
) => false,
|
||||
@@ -2602,6 +2622,8 @@ pub enum KnownClass {
|
||||
TypeVar,
|
||||
TypeAliasType,
|
||||
NoDefaultType,
|
||||
// TODO: This can probably be removed when we have support for protocols
|
||||
SupportsIndex,
|
||||
// Collections
|
||||
ChainMap,
|
||||
Counter,
|
||||
@@ -2652,6 +2674,7 @@ impl<'db> KnownClass {
|
||||
Self::TypeVar => "TypeVar",
|
||||
Self::TypeAliasType => "TypeAliasType",
|
||||
Self::NoDefaultType => "_NoDefaultType",
|
||||
Self::SupportsIndex => "SupportsIndex",
|
||||
Self::ChainMap => "ChainMap",
|
||||
Self::Counter => "Counter",
|
||||
Self::DefaultDict => "defaultdict",
|
||||
@@ -2733,9 +2756,11 @@ impl<'db> KnownClass {
|
||||
| Self::MethodWrapperType
|
||||
| Self::WrapperDescriptorType => KnownModule::Types,
|
||||
Self::NoneType => KnownModule::Typeshed,
|
||||
Self::SpecialForm | Self::TypeVar | Self::TypeAliasType | Self::StdlibAlias => {
|
||||
KnownModule::Typing
|
||||
}
|
||||
Self::SpecialForm
|
||||
| Self::TypeVar
|
||||
| Self::TypeAliasType
|
||||
| Self::StdlibAlias
|
||||
| Self::SupportsIndex => KnownModule::Typing,
|
||||
Self::NoDefaultType => {
|
||||
let python_version = Program::get(db).python_version(db);
|
||||
|
||||
@@ -2807,6 +2832,7 @@ impl<'db> KnownClass {
|
||||
| Self::Deque
|
||||
| Self::OrderedDict
|
||||
| Self::StdlibAlias
|
||||
| Self::SupportsIndex
|
||||
| Self::BaseException
|
||||
| Self::BaseExceptionGroup
|
||||
| Self::TypeVar => false,
|
||||
@@ -2852,6 +2878,7 @@ impl<'db> KnownClass {
|
||||
"_Alias" => Self::StdlibAlias,
|
||||
"_SpecialForm" => Self::SpecialForm,
|
||||
"_NoDefaultType" => Self::NoDefaultType,
|
||||
"SupportsIndex" => Self::SupportsIndex,
|
||||
"_version_info" => Self::VersionInfo,
|
||||
"ellipsis" if Program::get(db).python_version(db) <= PythonVersion::PY39 => {
|
||||
Self::EllipsisType
|
||||
@@ -2904,7 +2931,7 @@ impl<'db> KnownClass {
|
||||
| Self::MethodWrapperType
|
||||
| Self::WrapperDescriptorType => module == self.canonical_module(db),
|
||||
Self::NoneType => matches!(module, KnownModule::Typeshed | KnownModule::Types),
|
||||
Self::SpecialForm | Self::TypeVar | Self::TypeAliasType | Self::NoDefaultType => {
|
||||
Self::SpecialForm | Self::TypeVar | Self::TypeAliasType | Self::NoDefaultType | Self::SupportsIndex => {
|
||||
matches!(module, KnownModule::Typing | KnownModule::TypingExtensions)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user