diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_api.md b/crates/red_knot_python_semantic/resources/mdtest/type_api.md index 1bd7a0ca8b..bf93c9c3c2 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_api.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_api.md @@ -453,6 +453,5 @@ def _( # TODO: should be `(x: int) -> Foo` reveal_type(c4) # revealed: (...) -> Foo - # TODO: `self` is bound here; this should probably be `(x: int) -> str`? - reveal_type(c5) # revealed: (self, x: int) -> str + reveal_type(c5) # revealed: (x: int) -> str ``` diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 4a98680434..0b30254ee7 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -519,6 +519,10 @@ impl<'db> Type<'db> { matches!(self, Type::FunctionLiteral(..)) } + pub const fn is_bound_method(&self) -> bool { + matches!(self, Type::BoundMethod(..)) + } + pub fn is_union_of_single_valued(&self, db: &'db dyn Db) -> bool { self.into_union() .is_some_and(|union| union.elements(db).iter().all(|ty| ty.is_single_valued(db))) diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 60571aca6b..5ac2a966ca 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -6924,7 +6924,13 @@ impl<'db> TypeInferenceBuilder<'db> { return Type::unknown(); }; - Type::Callable(CallableType::new(db, signature.clone())) + let revealed_signature = if argument_type.is_bound_method() { + signature.bind_self() + } else { + signature.clone() + }; + + Type::Callable(CallableType::new(db, revealed_signature)) } },