diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md index b128fe8013..5ca7c9c628 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md +++ b/crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md @@ -504,4 +504,22 @@ c: Callable[[Any], str] = f c: Callable[[Any], str] = g ``` +### Method types + +```py +from typing import Any, Callable + +class A: + def f(self, x: Any) -> str: + return "" + + def g(self, x: Any) -> int: + return 1 + +c: Callable[[Any], str] = A().f + +# error: [invalid-assignment] "Object of type `bound method A.g(x: Any) -> int` is not assignable to `(Any, /) -> str`" +c: Callable[[Any], str] = A().g +``` + [typing documentation]: https://typing.python.org/en/latest/spec/concepts.html#the-assignable-to-or-consistent-subtyping-relation diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 6e33f79847..9f3b17f3b6 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -1368,6 +1368,10 @@ impl<'db> Type<'db> { .is_assignable_to(db, target) } + (Type::BoundMethod(self_bound_method), Type::Callable(_)) => self_bound_method + .into_callable_type(db) + .is_assignable_to(db, target), + // TODO other types containing gradual forms (e.g. generics containing Any/Unknown) _ => self.is_subtype_of(db, target), }