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 3937d2ee08..6f9cf78028 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 @@ -476,4 +476,21 @@ static_assert(is_assignable_to(CallableTypeOf[keyword_variadic], Callable[..., N static_assert(is_assignable_to(CallableTypeOf[mixed], Callable[..., None])) ``` +### Function types + +```py +from typing import Any, Callable + +def f(x: Any) -> str: + return "" + +def g(x: Any) -> int: + return 1 + +c: Callable[[Any], str] = f + +# error: [invalid-assignment] "Object of type `Literal[g]` is not assignable to `(Any, /) -> str`" +c: Callable[[Any], str] = g +``` + [typing documentation]: https://typing.readthedocs.io/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 d45ec530d8..d5ed2b6d77 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -900,6 +900,12 @@ impl<'db> Type<'db> { Type::Callable(CallableType::General(target_callable)), ) => self_callable.is_assignable_to(db, target_callable), + (Type::FunctionLiteral(self_function_literal), Type::Callable(_)) => { + self_function_literal + .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), }