mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
[red-knot] Fix gradual equivalence for callable types (#16887)
## Summary As mentioned in https://github.com/astral-sh/ruff/pull/16698#discussion_r2004920075, part of #15382, this PR updates the `is_gradual_equivalent_to` implementation between callable types to be similar to `is_equivalent_to` and checks other attributes of parameters like name, optionality, and parameter kind. ## Test Plan Expand the existing test cases to consider other properties but not all similar to how the tests are structured for subtyping and assignability.
This commit is contained in:
parent
68ea2b8b5b
commit
dd5b02aaa2
2 changed files with 67 additions and 60 deletions
|
@ -68,6 +68,10 @@ static_assert(not is_gradual_equivalent_to(tuple[str, int], tuple[int, str]))
|
|||
|
||||
## Callable
|
||||
|
||||
The examples provided below are only a subset of the possible cases and only include the ones with
|
||||
gradual types. The cases with fully static types and using different combinations of parameter kinds
|
||||
are covered in the [equivalence tests](./is_equivalent_to.md#callable).
|
||||
|
||||
```py
|
||||
from knot_extensions import Unknown, CallableTypeFromFunction, is_gradual_equivalent_to, static_assert
|
||||
from typing import Any, Callable
|
||||
|
@ -94,7 +98,7 @@ static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[f1], Callable[[]
|
|||
And, similarly for parameters with no annotations.
|
||||
|
||||
```py
|
||||
def f2(a, b) -> None:
|
||||
def f2(a, b, /) -> None:
|
||||
return
|
||||
|
||||
static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[f2], Callable[[Any, Any], None]))
|
||||
|
@ -115,8 +119,8 @@ static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[variadic_without
|
|||
static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[variadic_with_annotation], Callable[..., Any]))
|
||||
```
|
||||
|
||||
But, a function with either `*args` or `**kwargs` is not gradual equivalent to a callable with `...`
|
||||
as the parameter type.
|
||||
But, a function with either `*args` or `**kwargs` (and not both) is not gradual equivalent to a
|
||||
callable with `...` as the parameter type.
|
||||
|
||||
```py
|
||||
def variadic_args(*args):
|
||||
|
@ -129,4 +133,25 @@ static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[variadic_arg
|
|||
static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[variadic_kwargs], Callable[..., Any]))
|
||||
```
|
||||
|
||||
Parameter names, default values, and it's kind should also be considered when checking for gradual
|
||||
equivalence.
|
||||
|
||||
```py
|
||||
def f1(a): ...
|
||||
def f2(b): ...
|
||||
|
||||
static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[f1], CallableTypeFromFunction[f2]))
|
||||
|
||||
def f3(a=1): ...
|
||||
def f4(a=2): ...
|
||||
def f5(a): ...
|
||||
|
||||
static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[f3], CallableTypeFromFunction[f4]))
|
||||
static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[f3], CallableTypeFromFunction[f5]))
|
||||
|
||||
def f6(a, /): ...
|
||||
|
||||
static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[f1], CallableTypeFromFunction[f6]))
|
||||
```
|
||||
|
||||
[materializations]: https://typing.readthedocs.io/en/latest/spec/glossary.html#term-materialize
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue