[ty] "foo".startswith is not an instance of types.MethodWrapperType (#20317)

This commit is contained in:
Alex Waygood 2025-09-10 12:14:26 +01:00 committed by GitHub
parent fd7eb1e22f
commit b85c995927
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 236 additions and 151 deletions

View file

@ -2057,8 +2057,13 @@ reveal_type(f.__kwdefaults__) # revealed: dict[str, Any] | None
Some attributes are special-cased, however: Some attributes are special-cased, however:
```py ```py
import types
from ty_extensions import static_assert, TypeOf, is_subtype_of
reveal_type(f.__get__) # revealed: <method-wrapper `__get__` of `f`> reveal_type(f.__get__) # revealed: <method-wrapper `__get__` of `f`>
reveal_type(f.__call__) # revealed: <method-wrapper `__call__` of `f`> reveal_type(f.__call__) # revealed: <method-wrapper `__call__` of `f`>
static_assert(is_subtype_of(TypeOf[f.__get__], types.MethodWrapperType))
static_assert(is_subtype_of(TypeOf[f.__call__], types.MethodWrapperType))
``` ```
### Int-literal attributes ### Int-literal attributes

View file

@ -47,4 +47,19 @@ def _(string_instance: str, literalstring: LiteralString):
reveal_type("a".startswith(literalstring)) # revealed: bool reveal_type("a".startswith(literalstring)) # revealed: bool
``` ```
Unlike bound methods for some other classes implemented in C, `"foo".startswith` is an instance of
`types.BuiltinFunctionType` at runtime, rather than `types.MethodWrapperType`:
```py
import types
from ty_extensions import TypeOf, static_assert, is_subtype_of
static_assert(is_subtype_of(TypeOf["foo".startswith], types.BuiltinFunctionType))
# `types.BuiltinMethodType` is just an alias for `types.BuiltinFunctionType`
static_assert(is_subtype_of(TypeOf["foo".startswith], types.BuiltinMethodType))
static_assert(not is_subtype_of(TypeOf["foo".startswith], types.MethodWrapperType))
static_assert(not is_subtype_of(TypeOf["foo".startswith], types.WrapperDescriptorType))
```
[`sys.platform` checks]: https://docs.python.org/3/library/sys.html#sys.platform [`sys.platform` checks]: https://docs.python.org/3/library/sys.html#sys.platform

View file

@ -585,13 +585,16 @@ that method calls work as expected. See [this test suite](./call/methods.md) for
Here, we only demonstrate how `__get__` works on functions: Here, we only demonstrate how `__get__` works on functions:
```py ```py
import types
from inspect import getattr_static from inspect import getattr_static
from ty_extensions import static_assert, is_subtype_of, TypeOf
def f(x: object) -> str: def f(x: object) -> str:
return "a" return "a"
reveal_type(f) # revealed: def f(x: object) -> str reveal_type(f) # revealed: def f(x: object) -> str
reveal_type(f.__get__) # revealed: <method-wrapper `__get__` of `f`> reveal_type(f.__get__) # revealed: <method-wrapper `__get__` of `f`>
static_assert(is_subtype_of(TypeOf[f.__get__], types.MethodWrapperType))
reveal_type(f.__get__(None, type(f))) # revealed: def f(x: object) -> str reveal_type(f.__get__(None, type(f))) # revealed: def f(x: object) -> str
reveal_type(f.__get__(None, type(f))(1)) # revealed: str reveal_type(f.__get__(None, type(f))(1)) # revealed: str
@ -599,6 +602,7 @@ wrapper_descriptor = getattr_static(f, "__get__")
reveal_type(wrapper_descriptor) # revealed: <wrapper-descriptor `__get__` of `function` objects> reveal_type(wrapper_descriptor) # revealed: <wrapper-descriptor `__get__` of `function` objects>
reveal_type(wrapper_descriptor(f, None, type(f))) # revealed: def f(x: object) -> str reveal_type(wrapper_descriptor(f, None, type(f))) # revealed: def f(x: object) -> str
static_assert(is_subtype_of(TypeOf[wrapper_descriptor], types.WrapperDescriptorType))
# Attribute access on the method-wrapper `f.__get__` falls back to `MethodWrapperType`: # Attribute access on the method-wrapper `f.__get__` falls back to `MethodWrapperType`:
reveal_type(f.__get__.__hash__) # revealed: bound method MethodWrapperType.__hash__() -> int reveal_type(f.__get__.__hash__) # revealed: bound method MethodWrapperType.__hash__() -> int

View file

@ -303,3 +303,18 @@ reveal_type(attr_property.fset(c, "a")) # revealed: None
# error: [invalid-argument-type] # error: [invalid-argument-type]
attr_property.fset(c, 1) attr_property.fset(c, 1)
``` ```
At runtime, `attr_property.__get__` and `attr_property.__set__` are both instances of
`types.MethodWrapperType`:
```py
import types
from ty_extensions import TypeOf, static_assert, is_subtype_of
static_assert(is_subtype_of(TypeOf[attr_property.__get__], types.MethodWrapperType))
static_assert(is_subtype_of(TypeOf[attr_property.__set__], types.MethodWrapperType))
static_assert(not is_subtype_of(TypeOf[attr_property.__get__], types.WrapperDescriptorType))
static_assert(not is_subtype_of(TypeOf[attr_property.__set__], types.WrapperDescriptorType))
static_assert(not is_subtype_of(TypeOf[attr_property.__get__], types.BuiltinMethodType))
static_assert(not is_subtype_of(TypeOf[attr_property.__set__], types.BuiltinMethodType))
```

View file

@ -326,7 +326,7 @@ impl<'db> Completion<'db> {
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::Callable(_) => CompletionKind::Function, | Type::Callable(_) => CompletionKind::Function,
Type::BoundMethod(_) | Type::MethodWrapper(_) => CompletionKind::Method, Type::BoundMethod(_) | Type::KnownBoundMethod(_) => CompletionKind::Method,
Type::ModuleLiteral(_) => CompletionKind::Module, Type::ModuleLiteral(_) => CompletionKind::Module,
Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::SubclassOf(_) => { Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::SubclassOf(_) => {
CompletionKind::Class CompletionKind::Class

View file

@ -618,22 +618,21 @@ pub enum Type<'db> {
/// the `self` parameter, and return a `MethodType & Callable[[int], str]`. /// the `self` parameter, and return a `MethodType & Callable[[int], str]`.
/// One drawback would be that we could not show the bound instance when that type is displayed. /// One drawback would be that we could not show the bound instance when that type is displayed.
BoundMethod(BoundMethodType<'db>), BoundMethod(BoundMethodType<'db>),
/// Represents a specific instance of `types.MethodWrapperType`. /// Represents a specific instance of a bound method type for a builtin class.
/// ///
/// TODO: consider replacing this with `Callable & types.MethodWrapperType` type? /// TODO: consider replacing this with `Callable & types.MethodWrapperType` type?
/// Requires `Callable` to be able to represent overloads, e.g. `types.FunctionType.__get__` has /// The `Callable` type would need to be overloaded -- e.g. `types.FunctionType.__get__` has
/// this behaviour when a method is accessed on a class vs an instance: /// this behaviour when a method is accessed on a class vs an instance:
/// ///
/// ```txt /// ```txt
/// * (None, type) -> Literal[function_on_which_it_was_called] /// * (None, type) -> Literal[function_on_which_it_was_called]
/// * (object, type | None) -> BoundMethod[instance, function_on_which_it_was_called] /// * (object, type | None) -> BoundMethod[instance, function_on_which_it_was_called]
/// ``` /// ```
MethodWrapper(MethodWrapperKind<'db>), KnownBoundMethod(KnownBoundMethodType<'db>),
/// Represents a specific instance of `types.WrapperDescriptorType`. /// Represents a specific instance of `types.WrapperDescriptorType`.
/// ///
/// TODO: Similar to above, this could eventually be replaced by a generic `Callable` /// TODO: Similar to above, this could eventually be replaced by a generic `Callable`
/// type. We currently add this as a separate variant because `FunctionType.__get__` /// type.
/// is an overloaded method and we do not support `@overload` yet.
WrapperDescriptor(WrapperDescriptorKind), WrapperDescriptor(WrapperDescriptorKind),
/// A special callable that is returned by a `dataclass(…)` call. It is usually /// A special callable that is returned by a `dataclass(…)` call. It is usually
/// used as a decorator. Note that this is only used as a return type for actual /// used as a decorator. Note that this is only used as a return type for actual
@ -1121,8 +1120,8 @@ impl<'db> Type<'db> {
Type::PropertyInstance(property) => visitor.visit(self, || { Type::PropertyInstance(property) => visitor.visit(self, || {
Type::PropertyInstance(property.normalized_impl(db, visitor)) Type::PropertyInstance(property.normalized_impl(db, visitor))
}), }),
Type::MethodWrapper(method_kind) => visitor.visit(self, || { Type::KnownBoundMethod(method_kind) => visitor.visit(self, || {
Type::MethodWrapper(method_kind.normalized_impl(db, visitor)) Type::KnownBoundMethod(method_kind.normalized_impl(db, visitor))
}), }),
Type::BoundMethod(method) => visitor.visit(self, || { Type::BoundMethod(method) => visitor.visit(self, || {
Type::BoundMethod(method.normalized_impl(db, visitor)) Type::BoundMethod(method.normalized_impl(db, visitor))
@ -1192,7 +1191,7 @@ impl<'db> Type<'db> {
| Type::FunctionLiteral(..) | Type::FunctionLiteral(..)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(..) | Type::ModuleLiteral(..)
@ -1291,7 +1290,7 @@ impl<'db> Type<'db> {
| Type::TypedDict(_) => None, | Type::TypedDict(_) => None,
// TODO // TODO
Type::MethodWrapper(_) Type::KnownBoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
@ -1580,7 +1579,7 @@ impl<'db> Type<'db> {
(Type::BoundMethod(self_method), Type::BoundMethod(target_method)) => { (Type::BoundMethod(self_method), Type::BoundMethod(target_method)) => {
self_method.has_relation_to_impl(db, target_method, relation, visitor) self_method.has_relation_to_impl(db, target_method, relation, visitor)
} }
(Type::MethodWrapper(self_method), Type::MethodWrapper(target_method)) => { (Type::KnownBoundMethod(self_method), Type::KnownBoundMethod(target_method)) => {
self_method.has_relation_to_impl(db, target_method, relation, visitor) self_method.has_relation_to_impl(db, target_method, relation, visitor)
} }
@ -1662,7 +1661,8 @@ impl<'db> Type<'db> {
(Type::BoundMethod(_), _) => KnownClass::MethodType (Type::BoundMethod(_), _) => KnownClass::MethodType
.to_instance(db) .to_instance(db)
.has_relation_to_impl(db, target, relation, visitor), .has_relation_to_impl(db, target, relation, visitor),
(Type::MethodWrapper(_), _) => KnownClass::WrapperDescriptorType (Type::KnownBoundMethod(method), _) => method
.class()
.to_instance(db) .to_instance(db)
.has_relation_to_impl(db, target, relation, visitor), .has_relation_to_impl(db, target, relation, visitor),
(Type::WrapperDescriptor(_), _) => KnownClass::WrapperDescriptorType (Type::WrapperDescriptor(_), _) => KnownClass::WrapperDescriptorType
@ -1901,7 +1901,7 @@ impl<'db> Type<'db> {
(Type::BoundMethod(self_method), Type::BoundMethod(target_method)) => { (Type::BoundMethod(self_method), Type::BoundMethod(target_method)) => {
self_method.is_equivalent_to_impl(db, target_method, visitor) self_method.is_equivalent_to_impl(db, target_method, visitor)
} }
(Type::MethodWrapper(self_method), Type::MethodWrapper(target_method)) => { (Type::KnownBoundMethod(self_method), Type::KnownBoundMethod(target_method)) => {
self_method.is_equivalent_to_impl(db, target_method, visitor) self_method.is_equivalent_to_impl(db, target_method, visitor)
} }
(Type::Callable(first), Type::Callable(second)) => { (Type::Callable(first), Type::Callable(second)) => {
@ -2074,7 +2074,7 @@ impl<'db> Type<'db> {
| Type::EnumLiteral(..) | Type::EnumLiteral(..)
| Type::FunctionLiteral(..) | Type::FunctionLiteral(..)
| Type::BoundMethod(..) | Type::BoundMethod(..)
| Type::MethodWrapper(..) | Type::KnownBoundMethod(..)
| Type::WrapperDescriptor(..) | Type::WrapperDescriptor(..)
| Type::ModuleLiteral(..) | Type::ModuleLiteral(..)
| Type::ClassLiteral(..) | Type::ClassLiteral(..)
@ -2088,7 +2088,7 @@ impl<'db> Type<'db> {
| Type::EnumLiteral(..) | Type::EnumLiteral(..)
| Type::FunctionLiteral(..) | Type::FunctionLiteral(..)
| Type::BoundMethod(..) | Type::BoundMethod(..)
| Type::MethodWrapper(..) | Type::KnownBoundMethod(..)
| Type::WrapperDescriptor(..) | Type::WrapperDescriptor(..)
| Type::ModuleLiteral(..) | Type::ModuleLiteral(..)
| Type::ClassLiteral(..) | Type::ClassLiteral(..)
@ -2107,7 +2107,7 @@ impl<'db> Type<'db> {
| Type::EnumLiteral(..) | Type::EnumLiteral(..)
| Type::FunctionLiteral(..) | Type::FunctionLiteral(..)
| Type::BoundMethod(..) | Type::BoundMethod(..)
| Type::MethodWrapper(..) | Type::KnownBoundMethod(..)
| Type::WrapperDescriptor(..) | Type::WrapperDescriptor(..)
| Type::ModuleLiteral(..), | Type::ModuleLiteral(..),
) )
@ -2120,7 +2120,7 @@ impl<'db> Type<'db> {
| Type::EnumLiteral(..) | Type::EnumLiteral(..)
| Type::FunctionLiteral(..) | Type::FunctionLiteral(..)
| Type::BoundMethod(..) | Type::BoundMethod(..)
| Type::MethodWrapper(..) | Type::KnownBoundMethod(..)
| Type::WrapperDescriptor(..) | Type::WrapperDescriptor(..)
| Type::ModuleLiteral(..), | Type::ModuleLiteral(..),
Type::SubclassOf(_), Type::SubclassOf(_),
@ -2374,8 +2374,9 @@ impl<'db> Type<'db> {
.to_instance(db) .to_instance(db)
.is_disjoint_from_impl(db, other, visitor), .is_disjoint_from_impl(db, other, visitor),
(Type::MethodWrapper(_), other) | (other, Type::MethodWrapper(_)) => { (Type::KnownBoundMethod(method), other) | (other, Type::KnownBoundMethod(method)) => {
KnownClass::MethodWrapperType method
.class()
.to_instance(db) .to_instance(db)
.is_disjoint_from_impl(db, other, visitor) .is_disjoint_from_impl(db, other, visitor)
} }
@ -2562,7 +2563,7 @@ impl<'db> Type<'db> {
// ``` // ```
false false
} }
Type::MethodWrapper(_) => { Type::KnownBoundMethod(_) => {
// Just a special case of `BoundMethod` really // Just a special case of `BoundMethod` really
// (this variant represents `f.__get__`, where `f` is any function) // (this variant represents `f.__get__`, where `f` is any function)
false false
@ -2599,7 +2600,7 @@ impl<'db> Type<'db> {
Type::FunctionLiteral(..) Type::FunctionLiteral(..)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::ModuleLiteral(..) | Type::ModuleLiteral(..)
| Type::ClassLiteral(..) | Type::ClassLiteral(..)
| Type::GenericAlias(..) | Type::GenericAlias(..)
@ -2788,7 +2789,7 @@ impl<'db> Type<'db> {
| Type::Callable(_) | Type::Callable(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
@ -2900,9 +2901,9 @@ impl<'db> Type<'db> {
Type::BoundMethod(_) => KnownClass::MethodType Type::BoundMethod(_) => KnownClass::MethodType
.to_instance(db) .to_instance(db)
.instance_member(db, name), .instance_member(db, name),
Type::MethodWrapper(_) => KnownClass::MethodWrapperType Type::KnownBoundMethod(method) => {
.to_instance(db) method.class().to_instance(db).instance_member(db, name)
.instance_member(db, name), }
Type::WrapperDescriptor(_) => KnownClass::WrapperDescriptorType Type::WrapperDescriptor(_) => KnownClass::WrapperDescriptorType
.to_instance(db) .to_instance(db)
.instance_member(db, name), .instance_member(db, name),
@ -3326,23 +3327,23 @@ impl<'db> Type<'db> {
Type::Dynamic(..) | Type::Never => Place::bound(self).into(), Type::Dynamic(..) | Type::Never => Place::bound(self).into(),
Type::FunctionLiteral(function) if name == "__get__" => Place::bound( Type::FunctionLiteral(function) if name == "__get__" => Place::bound(
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)), Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(function)),
) )
.into(), .into(),
Type::FunctionLiteral(function) if name == "__call__" => Place::bound( Type::FunctionLiteral(function) if name == "__call__" => Place::bound(
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderCall(function)), Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderCall(function)),
) )
.into(), .into(),
Type::PropertyInstance(property) if name == "__get__" => Place::bound( Type::PropertyInstance(property) if name == "__get__" => Place::bound(
Type::MethodWrapper(MethodWrapperKind::PropertyDunderGet(property)), Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderGet(property)),
) )
.into(), .into(),
Type::PropertyInstance(property) if name == "__set__" => Place::bound( Type::PropertyInstance(property) if name == "__set__" => Place::bound(
Type::MethodWrapper(MethodWrapperKind::PropertyDunderSet(property)), Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderSet(property)),
) )
.into(), .into(),
Type::StringLiteral(literal) if name == "startswith" => Place::bound( Type::StringLiteral(literal) if name == "startswith" => Place::bound(
Type::MethodWrapper(MethodWrapperKind::StrStartswith(literal)), Type::KnownBoundMethod(KnownBoundMethodType::StrStartswith(literal)),
) )
.into(), .into(),
@ -3385,7 +3386,8 @@ impl<'db> Type<'db> {
}) })
} }
}, },
Type::MethodWrapper(_) => KnownClass::MethodWrapperType Type::KnownBoundMethod(method) => method
.class()
.to_instance(db) .to_instance(db)
.member_lookup_with_policy(db, name, policy), .member_lookup_with_policy(db, name, policy),
Type::WrapperDescriptor(_) => KnownClass::WrapperDescriptorType Type::WrapperDescriptor(_) => KnownClass::WrapperDescriptorType
@ -3786,7 +3788,7 @@ impl<'db> Type<'db> {
Type::FunctionLiteral(_) Type::FunctionLiteral(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
@ -3949,9 +3951,9 @@ impl<'db> Type<'db> {
.into() .into()
} }
Type::MethodWrapper( Type::KnownBoundMethod(
MethodWrapperKind::FunctionTypeDunderGet(_) KnownBoundMethodType::FunctionTypeDunderGet(_)
| MethodWrapperKind::PropertyDunderGet(_), | KnownBoundMethodType::PropertyDunderGet(_),
) => { ) => {
// Here, we dynamically model the overloaded function signature of `types.FunctionType.__get__`. // Here, we dynamically model the overloaded function signature of `types.FunctionType.__get__`.
// This is required because we need to return more precise types than what the signature in // This is required because we need to return more precise types than what the signature in
@ -4055,7 +4057,7 @@ impl<'db> Type<'db> {
.into() .into()
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderSet(_)) => Binding::single( Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderSet(_)) => Binding::single(
self, self,
Signature::new( Signature::new(
Parameters::new([ Parameters::new([
@ -4085,7 +4087,7 @@ impl<'db> Type<'db> {
) )
.into(), .into(),
Type::MethodWrapper(MethodWrapperKind::StrStartswith(_)) => Binding::single( Type::KnownBoundMethod(KnownBoundMethodType::StrStartswith(_)) => Binding::single(
self, self,
Signature::new( Signature::new(
Parameters::new([ Parameters::new([
@ -4814,7 +4816,7 @@ impl<'db> Type<'db> {
} }
// TODO: these are actually callable // TODO: these are actually callable
Type::MethodWrapper(_) | Type::DataclassDecorator(_) => { Type::KnownBoundMethod(_) | Type::DataclassDecorator(_) => {
CallableBinding::not_callable(self).into() CallableBinding::not_callable(self).into()
} }
@ -5065,7 +5067,7 @@ impl<'db> Type<'db> {
Type::FunctionLiteral(_) Type::FunctionLiteral(_)
| Type::GenericAlias(_) | Type::GenericAlias(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
@ -5527,7 +5529,7 @@ impl<'db> Type<'db> {
| Type::EnumLiteral(_) | Type::EnumLiteral(_)
| Type::FunctionLiteral(_) | Type::FunctionLiteral(_)
| Type::Callable(..) | Type::Callable(..)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
@ -5607,7 +5609,7 @@ impl<'db> Type<'db> {
| Type::Callable(_) | Type::Callable(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::Never | Type::Never
@ -5896,7 +5898,7 @@ impl<'db> Type<'db> {
Type::EnumLiteral(enum_literal) => Type::ClassLiteral(enum_literal.enum_class(db)), Type::EnumLiteral(enum_literal) => Type::ClassLiteral(enum_literal.enum_class(db)),
Type::FunctionLiteral(_) => KnownClass::FunctionType.to_class_literal(db), Type::FunctionLiteral(_) => KnownClass::FunctionType.to_class_literal(db),
Type::BoundMethod(_) => KnownClass::MethodType.to_class_literal(db), Type::BoundMethod(_) => KnownClass::MethodType.to_class_literal(db),
Type::MethodWrapper(_) => KnownClass::MethodWrapperType.to_class_literal(db), Type::KnownBoundMethod(method) => method.class().to_class_literal(db),
Type::WrapperDescriptor(_) => KnownClass::WrapperDescriptorType.to_class_literal(db), Type::WrapperDescriptor(_) => KnownClass::WrapperDescriptorType.to_class_literal(db),
Type::DataclassDecorator(_) => KnownClass::FunctionType.to_class_literal(db), Type::DataclassDecorator(_) => KnownClass::FunctionType.to_class_literal(db),
Type::Callable(callable) if callable.is_function_like(db) => { Type::Callable(callable) if callable.is_function_like(db) => {
@ -6095,26 +6097,26 @@ impl<'db> Type<'db> {
Type::ProtocolInstance(instance.apply_type_mapping_impl(db, type_mapping, visitor)) Type::ProtocolInstance(instance.apply_type_mapping_impl(db, type_mapping, visitor))
} }
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(function)) => {
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet( Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(
function.with_type_mapping(db, type_mapping), function.with_type_mapping(db, type_mapping),
)) ))
} }
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderCall(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderCall(function)) => {
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderCall( Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderCall(
function.with_type_mapping(db, type_mapping), function.with_type_mapping(db, type_mapping),
)) ))
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderGet(property)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderGet(property)) => {
Type::MethodWrapper(MethodWrapperKind::PropertyDunderGet( Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderGet(
property.apply_type_mapping_impl(db, type_mapping, visitor), property.apply_type_mapping_impl(db, type_mapping, visitor),
)) ))
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderSet(property)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderSet(property)) => {
Type::MethodWrapper(MethodWrapperKind::PropertyDunderSet( Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderSet(
property.apply_type_mapping_impl(db, type_mapping, visitor), property.apply_type_mapping_impl(db, type_mapping, visitor),
)) ))
} }
@ -6198,7 +6200,7 @@ impl<'db> Type<'db> {
| Type::AlwaysTruthy | Type::AlwaysTruthy
| Type::AlwaysFalsy | Type::AlwaysFalsy
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(MethodWrapperKind::StrStartswith(_)) | Type::KnownBoundMethod(KnownBoundMethodType::StrStartswith(_))
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
// A non-generic class never needs to be specialized. A generic class is specialized // A non-generic class never needs to be specialized. A generic class is specialized
@ -6266,16 +6268,16 @@ impl<'db> Type<'db> {
); );
} }
Type::MethodWrapper( Type::KnownBoundMethod(
MethodWrapperKind::FunctionTypeDunderGet(function) KnownBoundMethodType::FunctionTypeDunderGet(function)
| MethodWrapperKind::FunctionTypeDunderCall(function), | KnownBoundMethodType::FunctionTypeDunderCall(function),
) => { ) => {
function.find_legacy_typevars_impl(db, binding_context, typevars, visitor); function.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
Type::MethodWrapper( Type::KnownBoundMethod(
MethodWrapperKind::PropertyDunderGet(property) KnownBoundMethodType::PropertyDunderGet(property)
| MethodWrapperKind::PropertyDunderSet(property), | KnownBoundMethodType::PropertyDunderSet(property),
) => { ) => {
property.find_legacy_typevars_impl(db, binding_context, typevars, visitor); property.find_legacy_typevars_impl(db, binding_context, typevars, visitor);
} }
@ -6343,7 +6345,7 @@ impl<'db> Type<'db> {
| Type::AlwaysTruthy | Type::AlwaysTruthy
| Type::AlwaysFalsy | Type::AlwaysFalsy
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(MethodWrapperKind::StrStartswith(_)) | Type::KnownBoundMethod(KnownBoundMethodType::StrStartswith(_))
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
@ -6459,7 +6461,7 @@ impl<'db> Type<'db> {
| Self::BytesLiteral(_) | Self::BytesLiteral(_)
// TODO: For enum literals, it would be even better to jump to the definition of the specific member // TODO: For enum literals, it would be even better to jump to the definition of the specific member
| Self::EnumLiteral(_) | Self::EnumLiteral(_)
| Self::MethodWrapper(_) | Self::KnownBoundMethod(_)
| Self::WrapperDescriptor(_) | Self::WrapperDescriptor(_)
| Self::DataclassDecorator(_) | Self::DataclassDecorator(_)
| Self::DataclassTransformer(_) | Self::DataclassTransformer(_)
@ -6645,7 +6647,7 @@ impl<'db> VarianceInferable<'db> for Type<'db> {
Type::Dynamic(_) Type::Dynamic(_)
| Type::Never | Type::Never
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
@ -9153,11 +9155,14 @@ impl<'db> CallableType<'db> {
} }
} }
/// Represents a specific instance of `types.MethodWrapperType` /// Represents a specific instance of a bound method type for a builtin class.
///
/// Unlike bound methods of user-defined classes, these are not generally instances
/// of `types.BoundMethodType` at runtime.
#[derive( #[derive(
Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, salsa::Update, get_size2::GetSize, Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, salsa::Update, get_size2::GetSize,
)] )]
pub enum MethodWrapperKind<'db> { pub enum KnownBoundMethodType<'db> {
/// Method wrapper for `some_function.__get__` /// Method wrapper for `some_function.__get__`
FunctionTypeDunderGet(FunctionType<'db>), FunctionTypeDunderGet(FunctionType<'db>),
/// Method wrapper for `some_function.__call__` /// Method wrapper for `some_function.__call__`
@ -9176,29 +9181,29 @@ pub enum MethodWrapperKind<'db> {
pub(super) fn walk_method_wrapper_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>( pub(super) fn walk_method_wrapper_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
db: &'db dyn Db, db: &'db dyn Db,
method_wrapper: MethodWrapperKind<'db>, method_wrapper: KnownBoundMethodType<'db>,
visitor: &V, visitor: &V,
) { ) {
match method_wrapper { match method_wrapper {
MethodWrapperKind::FunctionTypeDunderGet(function) => { KnownBoundMethodType::FunctionTypeDunderGet(function) => {
visitor.visit_function_type(db, function); visitor.visit_function_type(db, function);
} }
MethodWrapperKind::FunctionTypeDunderCall(function) => { KnownBoundMethodType::FunctionTypeDunderCall(function) => {
visitor.visit_function_type(db, function); visitor.visit_function_type(db, function);
} }
MethodWrapperKind::PropertyDunderGet(property) => { KnownBoundMethodType::PropertyDunderGet(property) => {
visitor.visit_property_instance_type(db, property); visitor.visit_property_instance_type(db, property);
} }
MethodWrapperKind::PropertyDunderSet(property) => { KnownBoundMethodType::PropertyDunderSet(property) => {
visitor.visit_property_instance_type(db, property); visitor.visit_property_instance_type(db, property);
} }
MethodWrapperKind::StrStartswith(string_literal) => { KnownBoundMethodType::StrStartswith(string_literal) => {
visitor.visit_type(db, Type::StringLiteral(string_literal)); visitor.visit_type(db, Type::StringLiteral(string_literal));
} }
} }
} }
impl<'db> MethodWrapperKind<'db> { impl<'db> KnownBoundMethodType<'db> {
fn has_relation_to_impl<C: Constraints<'db>>( fn has_relation_to_impl<C: Constraints<'db>>(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
@ -9208,32 +9213,38 @@ impl<'db> MethodWrapperKind<'db> {
) -> C { ) -> C {
match (self, other) { match (self, other) {
( (
MethodWrapperKind::FunctionTypeDunderGet(self_function), KnownBoundMethodType::FunctionTypeDunderGet(self_function),
MethodWrapperKind::FunctionTypeDunderGet(other_function), KnownBoundMethodType::FunctionTypeDunderGet(other_function),
) => self_function.has_relation_to_impl(db, other_function, relation, visitor), ) => self_function.has_relation_to_impl(db, other_function, relation, visitor),
( (
MethodWrapperKind::FunctionTypeDunderCall(self_function), KnownBoundMethodType::FunctionTypeDunderCall(self_function),
MethodWrapperKind::FunctionTypeDunderCall(other_function), KnownBoundMethodType::FunctionTypeDunderCall(other_function),
) => self_function.has_relation_to_impl(db, other_function, relation, visitor), ) => self_function.has_relation_to_impl(db, other_function, relation, visitor),
(MethodWrapperKind::PropertyDunderGet(_), MethodWrapperKind::PropertyDunderGet(_)) (
| (MethodWrapperKind::PropertyDunderSet(_), MethodWrapperKind::PropertyDunderSet(_)) KnownBoundMethodType::PropertyDunderGet(_),
| (MethodWrapperKind::StrStartswith(_), MethodWrapperKind::StrStartswith(_)) => { KnownBoundMethodType::PropertyDunderGet(_),
)
| (
KnownBoundMethodType::PropertyDunderSet(_),
KnownBoundMethodType::PropertyDunderSet(_),
)
| (KnownBoundMethodType::StrStartswith(_), KnownBoundMethodType::StrStartswith(_)) => {
C::from_bool(db, self == other) C::from_bool(db, self == other)
} }
( (
MethodWrapperKind::FunctionTypeDunderGet(_) KnownBoundMethodType::FunctionTypeDunderGet(_)
| MethodWrapperKind::FunctionTypeDunderCall(_) | KnownBoundMethodType::FunctionTypeDunderCall(_)
| MethodWrapperKind::PropertyDunderGet(_) | KnownBoundMethodType::PropertyDunderGet(_)
| MethodWrapperKind::PropertyDunderSet(_) | KnownBoundMethodType::PropertyDunderSet(_)
| MethodWrapperKind::StrStartswith(_), | KnownBoundMethodType::StrStartswith(_),
MethodWrapperKind::FunctionTypeDunderGet(_) KnownBoundMethodType::FunctionTypeDunderGet(_)
| MethodWrapperKind::FunctionTypeDunderCall(_) | KnownBoundMethodType::FunctionTypeDunderCall(_)
| MethodWrapperKind::PropertyDunderGet(_) | KnownBoundMethodType::PropertyDunderGet(_)
| MethodWrapperKind::PropertyDunderSet(_) | KnownBoundMethodType::PropertyDunderSet(_)
| MethodWrapperKind::StrStartswith(_), | KnownBoundMethodType::StrStartswith(_),
) => C::unsatisfiable(db), ) => C::unsatisfiable(db),
} }
} }
@ -9246,51 +9257,68 @@ impl<'db> MethodWrapperKind<'db> {
) -> C { ) -> C {
match (self, other) { match (self, other) {
( (
MethodWrapperKind::FunctionTypeDunderGet(self_function), KnownBoundMethodType::FunctionTypeDunderGet(self_function),
MethodWrapperKind::FunctionTypeDunderGet(other_function), KnownBoundMethodType::FunctionTypeDunderGet(other_function),
) => self_function.is_equivalent_to_impl(db, other_function, visitor), ) => self_function.is_equivalent_to_impl(db, other_function, visitor),
( (
MethodWrapperKind::FunctionTypeDunderCall(self_function), KnownBoundMethodType::FunctionTypeDunderCall(self_function),
MethodWrapperKind::FunctionTypeDunderCall(other_function), KnownBoundMethodType::FunctionTypeDunderCall(other_function),
) => self_function.is_equivalent_to_impl(db, other_function, visitor), ) => self_function.is_equivalent_to_impl(db, other_function, visitor),
(MethodWrapperKind::PropertyDunderGet(_), MethodWrapperKind::PropertyDunderGet(_)) (
| (MethodWrapperKind::PropertyDunderSet(_), MethodWrapperKind::PropertyDunderSet(_)) KnownBoundMethodType::PropertyDunderGet(_),
| (MethodWrapperKind::StrStartswith(_), MethodWrapperKind::StrStartswith(_)) => { KnownBoundMethodType::PropertyDunderGet(_),
)
| (
KnownBoundMethodType::PropertyDunderSet(_),
KnownBoundMethodType::PropertyDunderSet(_),
)
| (KnownBoundMethodType::StrStartswith(_), KnownBoundMethodType::StrStartswith(_)) => {
C::from_bool(db, self == other) C::from_bool(db, self == other)
} }
( (
MethodWrapperKind::FunctionTypeDunderGet(_) KnownBoundMethodType::FunctionTypeDunderGet(_)
| MethodWrapperKind::FunctionTypeDunderCall(_) | KnownBoundMethodType::FunctionTypeDunderCall(_)
| MethodWrapperKind::PropertyDunderGet(_) | KnownBoundMethodType::PropertyDunderGet(_)
| MethodWrapperKind::PropertyDunderSet(_) | KnownBoundMethodType::PropertyDunderSet(_)
| MethodWrapperKind::StrStartswith(_), | KnownBoundMethodType::StrStartswith(_),
MethodWrapperKind::FunctionTypeDunderGet(_) KnownBoundMethodType::FunctionTypeDunderGet(_)
| MethodWrapperKind::FunctionTypeDunderCall(_) | KnownBoundMethodType::FunctionTypeDunderCall(_)
| MethodWrapperKind::PropertyDunderGet(_) | KnownBoundMethodType::PropertyDunderGet(_)
| MethodWrapperKind::PropertyDunderSet(_) | KnownBoundMethodType::PropertyDunderSet(_)
| MethodWrapperKind::StrStartswith(_), | KnownBoundMethodType::StrStartswith(_),
) => C::unsatisfiable(db), ) => C::unsatisfiable(db),
} }
} }
fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self { fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
match self { match self {
MethodWrapperKind::FunctionTypeDunderGet(function) => { KnownBoundMethodType::FunctionTypeDunderGet(function) => {
MethodWrapperKind::FunctionTypeDunderGet(function.normalized_impl(db, visitor)) KnownBoundMethodType::FunctionTypeDunderGet(function.normalized_impl(db, visitor))
} }
MethodWrapperKind::FunctionTypeDunderCall(function) => { KnownBoundMethodType::FunctionTypeDunderCall(function) => {
MethodWrapperKind::FunctionTypeDunderCall(function.normalized_impl(db, visitor)) KnownBoundMethodType::FunctionTypeDunderCall(function.normalized_impl(db, visitor))
} }
MethodWrapperKind::PropertyDunderGet(property) => { KnownBoundMethodType::PropertyDunderGet(property) => {
MethodWrapperKind::PropertyDunderGet(property.normalized_impl(db, visitor)) KnownBoundMethodType::PropertyDunderGet(property.normalized_impl(db, visitor))
} }
MethodWrapperKind::PropertyDunderSet(property) => { KnownBoundMethodType::PropertyDunderSet(property) => {
MethodWrapperKind::PropertyDunderSet(property.normalized_impl(db, visitor)) KnownBoundMethodType::PropertyDunderSet(property.normalized_impl(db, visitor))
} }
MethodWrapperKind::StrStartswith(_) => self, KnownBoundMethodType::StrStartswith(_) => self,
}
}
/// Return the [`KnownClass`] that inhabitants of this type are instances of at runtime
fn class(self) -> KnownClass {
match self {
KnownBoundMethodType::FunctionTypeDunderGet(_)
| KnownBoundMethodType::FunctionTypeDunderCall(_)
| KnownBoundMethodType::PropertyDunderGet(_)
| KnownBoundMethodType::PropertyDunderSet(_) => KnownClass::MethodWrapperType,
KnownBoundMethodType::StrStartswith(_) => KnownClass::BuiltinFunctionType,
} }
} }
} }

View file

@ -31,9 +31,9 @@ use crate::types::generics::{Specialization, SpecializationBuilder, Specializati
use crate::types::signatures::{Parameter, ParameterForm, Parameters}; use crate::types::signatures::{Parameter, ParameterForm, Parameters};
use crate::types::tuple::{Tuple, TupleLength, TupleType}; use crate::types::tuple::{Tuple, TupleLength, TupleType};
use crate::types::{ use crate::types::{
BoundMethodType, ClassLiteral, DataclassParams, FieldInstance, KnownClass, KnownInstanceType, BoundMethodType, ClassLiteral, DataclassParams, FieldInstance, KnownBoundMethodType,
MethodWrapperKind, PropertyInstanceType, SpecialFormType, TypeAliasType, TypeMapping, KnownClass, KnownInstanceType, PropertyInstanceType, SpecialFormType, TypeAliasType,
UnionType, WrapperDescriptorKind, enums, ide_support, todo_type, TypeMapping, UnionType, WrapperDescriptorKind, enums, ide_support, todo_type,
}; };
use ruff_db::diagnostic::{Annotation, Diagnostic, SubDiagnostic, SubDiagnosticSeverity}; use ruff_db::diagnostic::{Annotation, Diagnostic, SubDiagnostic, SubDiagnosticSeverity};
use ruff_python_ast::{self as ast, PythonVersion}; use ruff_python_ast::{self as ast, PythonVersion};
@ -271,7 +271,9 @@ impl<'db> Bindings<'db> {
let binding_type = binding.callable_type; let binding_type = binding.callable_type;
for (overload_index, overload) in binding.matching_overloads_mut() { for (overload_index, overload) in binding.matching_overloads_mut() {
match binding_type { match binding_type {
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(
function,
)) => {
if function.is_classmethod(db) { if function.is_classmethod(db) {
match overload.parameter_types() { match overload.parameter_types() {
[_, Some(owner)] => { [_, Some(owner)] => {
@ -435,7 +437,7 @@ impl<'db> Bindings<'db> {
} }
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderGet(property)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderGet(property)) => {
match overload.parameter_types() { match overload.parameter_types() {
[Some(instance), ..] if instance.is_none(db) => { [Some(instance), ..] if instance.is_none(db) => {
overload.set_return_type(Type::PropertyInstance(property)); overload.set_return_type(Type::PropertyInstance(property));
@ -488,7 +490,7 @@ impl<'db> Bindings<'db> {
} }
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderSet(property)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderSet(property)) => {
if let [Some(instance), Some(value), ..] = overload.parameter_types() { if let [Some(instance), Some(value), ..] = overload.parameter_types() {
if let Some(setter) = property.setter(db) { if let Some(setter) = property.setter(db) {
if let Err(_call_error) = setter if let Err(_call_error) = setter
@ -506,7 +508,7 @@ impl<'db> Bindings<'db> {
} }
} }
Type::MethodWrapper(MethodWrapperKind::StrStartswith(literal)) => { Type::KnownBoundMethod(KnownBoundMethodType::StrStartswith(literal)) => {
if let [Some(Type::StringLiteral(prefix)), None, None] = if let [Some(Type::StringLiteral(prefix)), None, None] =
overload.parameter_types() overload.parameter_types()
{ {
@ -1766,9 +1768,9 @@ impl<'db> CallableBinding<'db> {
FunctionKind::BoundMethod, FunctionKind::BoundMethod,
bound_method.function(context.db()), bound_method.function(context.db()),
)), )),
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(
Some((FunctionKind::MethodWrapper, function)) function,
} )) => Some((FunctionKind::MethodWrapper, function)),
_ => None, _ => None,
}; };
@ -2730,13 +2732,13 @@ impl<'db> CallableDescription<'db> {
kind: "bound method", kind: "bound method",
name: bound_method.function(db).name(db), name: bound_method.function(db).name(db),
}), }),
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(function)) => {
Some(CallableDescription { Some(CallableDescription {
kind: "method wrapper `__get__` of function", kind: "method wrapper `__get__` of function",
name: function.name(db), name: function.name(db),
}) })
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderGet(_)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderGet(_)) => {
Some(CallableDescription { Some(CallableDescription {
kind: "method wrapper", kind: "method wrapper",
name: "`__get__` of property", name: "`__get__` of property",

View file

@ -3610,6 +3610,11 @@ pub enum KnownClass {
GeneratorType, GeneratorType,
AsyncGeneratorType, AsyncGeneratorType,
CoroutineType, CoroutineType,
NotImplementedType,
BuiltinFunctionType,
// Exposed as `types.EllipsisType` on Python >=3.10;
// backported as `builtins.ellipsis` by typeshed on Python <=3.9
EllipsisType,
// Typeshed // Typeshed
NoneType, // Part of `types` for Python >= 3.10 NoneType, // Part of `types` for Python >= 3.10
// Typing // Typing
@ -3637,10 +3642,6 @@ pub enum KnownClass {
OrderedDict, OrderedDict,
// sys // sys
VersionInfo, VersionInfo,
// Exposed as `types.EllipsisType` on Python >=3.10;
// backported as `builtins.ellipsis` by typeshed on Python <=3.9
EllipsisType,
NotImplementedType,
// dataclasses // dataclasses
Field, Field,
KwOnly, KwOnly,
@ -3694,6 +3695,7 @@ impl KnownClass {
| Self::AsyncGeneratorType | Self::AsyncGeneratorType
| Self::MethodWrapperType | Self::MethodWrapperType
| Self::CoroutineType | Self::CoroutineType
| Self::BuiltinFunctionType
| Self::Template => Some(Truthiness::AlwaysTrue), | Self::Template => Some(Truthiness::AlwaysTrue),
Self::NoneType => Some(Truthiness::AlwaysFalse), Self::NoneType => Some(Truthiness::AlwaysFalse),
@ -3829,6 +3831,7 @@ impl KnownClass {
| KnownClass::NamedTupleFallback | KnownClass::NamedTupleFallback
| KnownClass::NamedTupleLike | KnownClass::NamedTupleLike
| KnownClass::TypedDictFallback | KnownClass::TypedDictFallback
| KnownClass::BuiltinFunctionType
| KnownClass::Template => false, | KnownClass::Template => false,
} }
} }
@ -3906,6 +3909,7 @@ impl KnownClass {
| KnownClass::NamedTupleFallback | KnownClass::NamedTupleFallback
| KnownClass::NamedTupleLike | KnownClass::NamedTupleLike
| KnownClass::TypedDictFallback | KnownClass::TypedDictFallback
| KnownClass::BuiltinFunctionType
| KnownClass::Template => false, | KnownClass::Template => false,
} }
} }
@ -3982,6 +3986,7 @@ impl KnownClass {
| KnownClass::TypedDictFallback | KnownClass::TypedDictFallback
| KnownClass::NamedTupleLike | KnownClass::NamedTupleLike
| KnownClass::NamedTupleFallback | KnownClass::NamedTupleFallback
| KnownClass::BuiltinFunctionType
| KnownClass::Template => false, | KnownClass::Template => false,
} }
} }
@ -4071,6 +4076,7 @@ impl KnownClass {
| Self::InitVar | Self::InitVar
| Self::NamedTupleFallback | Self::NamedTupleFallback
| Self::TypedDictFallback | Self::TypedDictFallback
| Self::BuiltinFunctionType
| Self::Template => false, | Self::Template => false,
} }
} }
@ -4109,6 +4115,7 @@ impl KnownClass {
Self::UnionType => "UnionType", Self::UnionType => "UnionType",
Self::MethodWrapperType => "MethodWrapperType", Self::MethodWrapperType => "MethodWrapperType",
Self::WrapperDescriptorType => "WrapperDescriptorType", Self::WrapperDescriptorType => "WrapperDescriptorType",
Self::BuiltinFunctionType => "BuiltinFunctionType",
Self::GeneratorType => "GeneratorType", Self::GeneratorType => "GeneratorType",
Self::AsyncGeneratorType => "AsyncGeneratorType", Self::AsyncGeneratorType => "AsyncGeneratorType",
Self::CoroutineType => "CoroutineType", Self::CoroutineType => "CoroutineType",
@ -4385,6 +4392,7 @@ impl KnownClass {
| Self::CoroutineType | Self::CoroutineType
| Self::MethodWrapperType | Self::MethodWrapperType
| Self::UnionType | Self::UnionType
| Self::BuiltinFunctionType
| Self::WrapperDescriptorType => KnownModule::Types, | Self::WrapperDescriptorType => KnownModule::Types,
Self::NoneType => KnownModule::Typeshed, Self::NoneType => KnownModule::Typeshed,
Self::Awaitable Self::Awaitable
@ -4511,6 +4519,7 @@ impl KnownClass {
| Self::NamedTupleFallback | Self::NamedTupleFallback
| Self::NamedTupleLike | Self::NamedTupleLike
| Self::TypedDictFallback | Self::TypedDictFallback
| Self::BuiltinFunctionType
| Self::Template => Some(false), | Self::Template => Some(false),
Self::Tuple => None, Self::Tuple => None,
@ -4593,6 +4602,7 @@ impl KnownClass {
| Self::NamedTupleFallback | Self::NamedTupleFallback
| Self::NamedTupleLike | Self::NamedTupleLike
| Self::TypedDictFallback | Self::TypedDictFallback
| Self::BuiltinFunctionType
| Self::Template => false, | Self::Template => false,
} }
} }
@ -4641,6 +4651,7 @@ impl KnownClass {
"UnionType" => Self::UnionType, "UnionType" => Self::UnionType,
"MethodWrapperType" => Self::MethodWrapperType, "MethodWrapperType" => Self::MethodWrapperType,
"WrapperDescriptorType" => Self::WrapperDescriptorType, "WrapperDescriptorType" => Self::WrapperDescriptorType,
"BuiltinFunctionType" => Self::BuiltinFunctionType,
"NewType" => Self::NewType, "NewType" => Self::NewType,
"TypeAliasType" => Self::TypeAliasType, "TypeAliasType" => Self::TypeAliasType,
"TypeVar" => Self::TypeVar, "TypeVar" => Self::TypeVar,
@ -4743,6 +4754,7 @@ impl KnownClass {
| Self::AsyncGeneratorType | Self::AsyncGeneratorType
| Self::CoroutineType | Self::CoroutineType
| Self::WrapperDescriptorType | Self::WrapperDescriptorType
| Self::BuiltinFunctionType
| Self::Field | Self::Field
| Self::KwOnly | Self::KwOnly
| Self::InitVar | Self::InitVar

View file

@ -140,7 +140,7 @@ impl<'db> ClassBase<'db> {
| Type::FunctionLiteral(_) | Type::FunctionLiteral(_)
| Type::Callable(..) | Type::Callable(..)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)

View file

@ -16,8 +16,8 @@ use crate::types::generics::{GenericContext, Specialization};
use crate::types::signatures::{CallableSignature, Parameter, Parameters, Signature}; use crate::types::signatures::{CallableSignature, Parameter, Parameters, Signature};
use crate::types::tuple::TupleSpec; use crate::types::tuple::TupleSpec;
use crate::types::{ use crate::types::{
BoundTypeVarInstance, CallableType, IntersectionType, KnownClass, MaterializationKind, BoundTypeVarInstance, CallableType, IntersectionType, KnownBoundMethodType, KnownClass,
MethodWrapperKind, Protocol, ProtocolInstanceType, StringLiteralType, SubclassOfInner, Type, MaterializationKind, Protocol, ProtocolInstanceType, StringLiteralType, SubclassOfInner, Type,
UnionType, WrapperDescriptorKind, UnionType, WrapperDescriptorKind,
}; };
use ruff_db::parsed::parsed_module; use ruff_db::parsed::parsed_module;
@ -368,27 +368,27 @@ impl Display for DisplayRepresentation<'_> {
} }
} }
} }
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderGet(function)) => {
write!( write!(
f, f,
"<method-wrapper `__get__` of `{function}`>", "<method-wrapper `__get__` of `{function}`>",
function = function.name(self.db), function = function.name(self.db),
) )
} }
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderCall(function)) => { Type::KnownBoundMethod(KnownBoundMethodType::FunctionTypeDunderCall(function)) => {
write!( write!(
f, f,
"<method-wrapper `__call__` of `{function}`>", "<method-wrapper `__call__` of `{function}`>",
function = function.name(self.db), function = function.name(self.db),
) )
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderGet(_)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderGet(_)) => {
f.write_str("<method-wrapper `__get__` of `property` object>") f.write_str("<method-wrapper `__get__` of `property` object>")
} }
Type::MethodWrapper(MethodWrapperKind::PropertyDunderSet(_)) => { Type::KnownBoundMethod(KnownBoundMethodType::PropertyDunderSet(_)) => {
f.write_str("<method-wrapper `__set__` of `property` object>") f.write_str("<method-wrapper `__set__` of `property` object>")
} }
Type::MethodWrapper(MethodWrapperKind::StrStartswith(_)) => { Type::KnownBoundMethod(KnownBoundMethodType::StrStartswith(_)) => {
f.write_str("<method-wrapper `startswith` of `str` object>") f.write_str("<method-wrapper `startswith` of `str` object>")
} }
Type::WrapperDescriptor(kind) => { Type::WrapperDescriptor(kind) => {
@ -1353,7 +1353,7 @@ impl Display for DisplayMaybeParenthesizedType<'_> {
|f: &mut Formatter<'_>| write!(f, "({})", self.ty.display_with(self.db, self.settings)); |f: &mut Formatter<'_>| write!(f, "({})", self.ty.display_with(self.db, self.settings));
match self.ty { match self.ty {
Type::Callable(_) Type::Callable(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::FunctionLiteral(_) | Type::FunctionLiteral(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::Union(_) => write_parentheses(f), | Type::Union(_) => write_parentheses(f),

View file

@ -1095,7 +1095,7 @@ fn is_instance_truthiness<'db>(
Type::TypeAlias(alias) => is_instance_truthiness(db, alias.value_type(db), class), Type::TypeAlias(alias) => is_instance_truthiness(db, alias.value_type(db), class),
Type::BoundMethod(..) Type::BoundMethod(..)
| Type::MethodWrapper(..) | Type::KnownBoundMethod(..)
| Type::WrapperDescriptor(..) | Type::WrapperDescriptor(..)
| Type::DataclassDecorator(..) | Type::DataclassDecorator(..)
| Type::DataclassTransformer(..) | Type::DataclassTransformer(..)

View file

@ -143,7 +143,7 @@ impl<'db> AllMembers<'db> {
| Type::PropertyInstance(_) | Type::PropertyInstance(_)
| Type::FunctionLiteral(_) | Type::FunctionLiteral(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)

View file

@ -4087,7 +4087,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
| Type::FunctionLiteral(..) | Type::FunctionLiteral(..)
| Type::Callable(..) | Type::Callable(..)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
@ -7388,7 +7388,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
Type::FunctionLiteral(_) Type::FunctionLiteral(_)
| Type::Callable(..) | Type::Callable(..)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::BoundMethod(_) | Type::BoundMethod(_)
@ -7731,7 +7731,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
| Type::Callable(..) | Type::Callable(..)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
@ -7761,7 +7761,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
| Type::Callable(..) | Type::Callable(..)
| Type::BoundMethod(_) | Type::BoundMethod(_)
| Type::WrapperDescriptor(_) | Type::WrapperDescriptor(_)
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::DataclassTransformer(_) | Type::DataclassTransformer(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)

View file

@ -240,7 +240,7 @@ impl ClassInfoConstraintFunction {
| Type::Callable(_) | Type::Callable(_)
| Type::DataclassDecorator(_) | Type::DataclassDecorator(_)
| Type::Never | Type::Never
| Type::MethodWrapper(_) | Type::KnownBoundMethod(_)
| Type::ModuleLiteral(_) | Type::ModuleLiteral(_)
| Type::FunctionLiteral(_) | Type::FunctionLiteral(_)
| Type::ProtocolInstance(_) | Type::ProtocolInstance(_)

View file

@ -76,9 +76,9 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::BoundMethod(_), _) => Ordering::Less, (Type::BoundMethod(_), _) => Ordering::Less,
(_, Type::BoundMethod(_)) => Ordering::Greater, (_, Type::BoundMethod(_)) => Ordering::Greater,
(Type::MethodWrapper(left), Type::MethodWrapper(right)) => left.cmp(right), (Type::KnownBoundMethod(left), Type::KnownBoundMethod(right)) => left.cmp(right),
(Type::MethodWrapper(_), _) => Ordering::Less, (Type::KnownBoundMethod(_), _) => Ordering::Less,
(_, Type::MethodWrapper(_)) => Ordering::Greater, (_, Type::KnownBoundMethod(_)) => Ordering::Greater,
(Type::WrapperDescriptor(left), Type::WrapperDescriptor(right)) => left.cmp(right), (Type::WrapperDescriptor(left), Type::WrapperDescriptor(right)) => left.cmp(right),
(Type::WrapperDescriptor(_), _) => Ordering::Less, (Type::WrapperDescriptor(_), _) => Ordering::Less,

View file

@ -2,7 +2,7 @@ use crate::{
Db, FxIndexSet, Db, FxIndexSet,
types::{ types::{
BoundMethodType, BoundSuperType, BoundTypeVarInstance, CallableType, GenericAlias, BoundMethodType, BoundSuperType, BoundTypeVarInstance, CallableType, GenericAlias,
IntersectionType, KnownInstanceType, MethodWrapperKind, NominalInstanceType, IntersectionType, KnownBoundMethodType, KnownInstanceType, NominalInstanceType,
PropertyInstanceType, ProtocolInstanceType, SubclassOfType, Type, TypeAliasType, PropertyInstanceType, ProtocolInstanceType, SubclassOfType, Type, TypeAliasType,
TypeIsType, TypeVarInstance, TypedDictType, UnionType, TypeIsType, TypeVarInstance, TypedDictType, UnionType,
class::walk_generic_alias, class::walk_generic_alias,
@ -81,7 +81,11 @@ pub(crate) trait TypeVisitor<'db> {
walk_protocol_instance_type(db, protocol, self); walk_protocol_instance_type(db, protocol, self);
} }
fn visit_method_wrapper_type(&self, db: &'db dyn Db, method_wrapper: MethodWrapperKind<'db>) { fn visit_method_wrapper_type(
&self,
db: &'db dyn Db,
method_wrapper: KnownBoundMethodType<'db>,
) {
walk_method_wrapper_type(db, method_wrapper, self); walk_method_wrapper_type(db, method_wrapper, self);
} }
@ -106,7 +110,7 @@ enum NonAtomicType<'db> {
FunctionLiteral(FunctionType<'db>), FunctionLiteral(FunctionType<'db>),
BoundMethod(BoundMethodType<'db>), BoundMethod(BoundMethodType<'db>),
BoundSuper(BoundSuperType<'db>), BoundSuper(BoundSuperType<'db>),
MethodWrapper(MethodWrapperKind<'db>), MethodWrapper(KnownBoundMethodType<'db>),
Callable(CallableType<'db>), Callable(CallableType<'db>),
GenericAlias(GenericAlias<'db>), GenericAlias(GenericAlias<'db>),
KnownInstance(KnownInstanceType<'db>), KnownInstance(KnownInstanceType<'db>),
@ -158,7 +162,7 @@ impl<'db> From<Type<'db>> for TypeKind<'db> {
Type::BoundSuper(bound_super) => { Type::BoundSuper(bound_super) => {
TypeKind::NonAtomic(NonAtomicType::BoundSuper(bound_super)) TypeKind::NonAtomic(NonAtomicType::BoundSuper(bound_super))
} }
Type::MethodWrapper(method_wrapper) => { Type::KnownBoundMethod(method_wrapper) => {
TypeKind::NonAtomic(NonAtomicType::MethodWrapper(method_wrapper)) TypeKind::NonAtomic(NonAtomicType::MethodWrapper(method_wrapper))
} }
Type::Callable(callable) => TypeKind::NonAtomic(NonAtomicType::Callable(callable)), Type::Callable(callable) => TypeKind::NonAtomic(NonAtomicType::Callable(callable)),