diff --git a/crates/ty_python_semantic/resources/mdtest/ty_extensions.md b/crates/ty_python_semantic/resources/mdtest/ty_extensions.md index 0d93d3ed2e..8c3730e9b2 100644 --- a/crates/ty_python_semantic/resources/mdtest/ty_extensions.md +++ b/crates/ty_python_semantic/resources/mdtest/ty_extensions.md @@ -469,6 +469,8 @@ c4: CallableTypeOf[()] Using it in annotation to reveal the signature of the callable object: ```py +from typing_extensions import Self + class Foo: def __init__(self, x: int) -> None: pass @@ -476,12 +478,16 @@ class Foo: def __call__(self, x: int) -> str: return "foo" + def returns_self(self, x: int) -> Self: + return self + def _( c1: CallableTypeOf[f1], c2: CallableTypeOf[f2], c3: CallableTypeOf[f3], c4: CallableTypeOf[Foo], c5: CallableTypeOf[Foo(42).__call__], + c6: CallableTypeOf[Foo(42).returns_self], ) -> None: reveal_type(c1) # revealed: () -> Unknown reveal_type(c2) # revealed: () -> int @@ -491,4 +497,6 @@ def _( reveal_type(c4) # revealed: (...) -> Foo reveal_type(c5) # revealed: (x: int) -> str + + reveal_type(c6) # revealed: (x: int) -> Foo ``` diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 636839f4f3..7126af975a 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -1046,8 +1046,11 @@ impl<'db> Type<'db> { matches!(self, Type::FunctionLiteral(..)) } - pub(crate) const fn is_bound_method(&self) -> bool { - matches!(self, Type::BoundMethod(..)) + pub(crate) const fn into_bound_method(self) -> Option> { + match self { + Type::BoundMethod(bound_method) => Some(bound_method), + _ => None, + } } pub(crate) fn is_union_of_single_valued(&self, db: &'db dyn Db) -> bool { diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs index 439b3cf1b8..8356be44bb 100644 --- a/crates/ty_python_semantic/src/types/infer.rs +++ b/crates/ty_python_semantic/src/types/infer.rs @@ -11040,8 +11040,10 @@ impl<'db> TypeInferenceBuilder<'db, '_> { .expect("`Bindings` should have at least one `CallableBinding`"); let mut signature_iter = callable_binding.into_iter().map(|binding| { - if argument_type.is_bound_method() { - binding.signature.bind_self(self.db(), Some(argument_type)) + if let Some(bound_method) = argument_type.into_bound_method() { + binding + .signature + .bind_self(self.db(), Some(bound_method.self_instance(db))) } else { binding.signature.clone() }