Model fallback MethodType => FunctionType

This commit is contained in:
David Peter
2025-02-20 15:22:05 +01:00
parent cc5270ae9c
commit fed67170ec
2 changed files with 20 additions and 2 deletions

View File

@@ -89,6 +89,14 @@ If we access an attribute on a bound method object itself, it will defer to `typ
reveal_type(bound_method.__hash__) # revealed: <bound method `__hash__` of `MethodType`>
```
If an attribute is not available on the bound method object, it will be looked up on the underlying
function object. We model this explicitly, which means that we can access `__module__` on bound
methods, even though it is not available on `types.MethodType`:
```py
reveal_type(bound_method.__module__) # revealed: str
```
## Basic method calls on class objects and instances
```py

View File

@@ -1607,7 +1607,17 @@ impl<'db> Type<'db> {
Type::Callable(CallableType::BoundMethod(bound_method)) => match name {
"__self__" => Symbol::bound(bound_method.self_instance(db)),
"__func__" => Symbol::bound(Type::FunctionLiteral(bound_method.function(db))),
_ => KnownClass::MethodType.to_instance(db).member(db, name),
_ => {
let member = KnownClass::MethodType.to_instance(db).member(db, name);
// If an attribute is not available on the bound method object, it will be looked
// up on the underlying function object:
if member.is_unbound() {
Type::FunctionLiteral(bound_method.function(db)).member(db, name)
} else {
member
}
}
},
Type::Callable(CallableType::MethodWrapperDunderGet(_)) => {
KnownClass::MethodWrapperType
@@ -3747,7 +3757,7 @@ impl KnownFunction {
}
}
/// This type represents bound method objects that are created when a method is called
/// This type represents bound method objects that are created when a method is accessed
/// on an instance of a class. For example, the expression `Path("a.txt").touch` creates
/// a bound method object that represents the `Path.touch` method which is bound to the
/// instance `Path("a.txt")`.