[red-knot] Add assignability of function literals to callables (#17095)

## Summary

Part  of #16953

## Test Plan

Update is_assignable_to.md

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
This commit is contained in:
Matthew Mckee 2025-03-31 16:42:42 +01:00 committed by GitHub
parent 491a51960e
commit 4a6fa5fc27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 0 deletions

View File

@ -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

View File

@ -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),
}