Skip to content

Conversation

@dhruvmanila
Copy link
Member

@dhruvmanila dhruvmanila commented Mar 11, 2025

Summary

Part of #15382

Add support for checking the gradual equivalence between callable types.

A callable type is gradually equivalent to the other callable type:

  • Both uses gradual form for the parameters. If not, then the number of parameters should be the same and the type at the a position in the first parameter list should be gradually equivalent the the type at the same position in the second parameter list
  • Both the return types are either None or the some values are gradually equivalent to each other.

Test Plan

Update is_gradual_equivalent_to.md with callable type test cases.

Note: I've an explicit goal of updating the property tests with the new callable types once all relations are implemented.

@dhruvmanila dhruvmanila added the ty Multi-file analysis & type inference label Mar 11, 2025
@dhruvmanila dhruvmanila force-pushed the dhruv/callable-is-gradual-equivalent-to branch from 5e2ccec to 26676b7 Compare March 11, 2025 16:31
@github-actions
Copy link
Contributor

github-actions bot commented Mar 11, 2025

mypy_primer results

No ecosystem changes detected ✅

Copy link
Contributor

@sharkdp sharkdp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart for the one question I had, this looks good to me. Thank you.

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I guess this (and the other similar PRs) will probably need some adjustment rebased on top of @dcreager's overload support.

@dhruvmanila dhruvmanila force-pushed the dhruv/callable-is-gradual-equivalent-to branch from 26676b7 to dffee4f Compare March 12, 2025 16:09
@dhruvmanila dhruvmanila changed the base branch from main to dhruv/callable-type-from-function March 12, 2025 16:10
Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

dhruvmanila added a commit that referenced this pull request Mar 13, 2025
## Summary

This PR adds a new `CallableTypeFromFunction` special form to allow
extracting the abstract signature of a function literal i.e., convert a
`Type::Function` into a `Type::Callable` (`CallableType::General`).

This is done to support testing the `is_gradual_equivalent_to` type
relation specifically the case we want to make sure that a function that
has parameters with no annotations and does not have a return type
annotation is gradual equivalent to `Callable[[Any, Any, ...], Any]`
where the number of parameters should match between the function literal
and callable type.

Refer
#16634 (comment)

### Bikeshedding

The name `CallableTypeFromFunction` is a bit too verbose. A possibly
alternative from Carl is `CallableTypeOf` but that would be similar to
`TypeOf` albeit with a limitation that the former only accepts function
literal types and errors on other types.

Some other alternatives:
* `FunctionSignature`
* `SignatureOf` (similar issues as `TypeOf`?)
* ...

## Test Plan

Update `type_api.md` with a new section that tests this special form,
both invalid and valid forms.
Base automatically changed from dhruv/callable-type-from-function to main March 13, 2025 02:19
@dhruvmanila dhruvmanila force-pushed the dhruv/callable-is-gradual-equivalent-to branch from dffee4f to 9dac249 Compare March 13, 2025 02:20
@dhruvmanila
Copy link
Member Author

I found one more case which we need to consider:

def foo(*args: Any, **kwargs: Any) -> Any:
    pass

static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[foo], Callable[..., Any]))

Because, as per the spec:

If the input signature in a function definition includes both a *args and **kwargs parameter and both are typed as Any (explicitly or implicitly because it has no annotation), a type checker should treat this as the equivalent of ....

https://typing.python.org/en/latest/spec/callables.html#meaning-of-in-callable

@dhruvmanila
Copy link
Member Author

Oh, that's simple to fix. I don't need to explicitly check whether both signatures has is_gradual flag as true because even in the case of ..., the parameters is populated with *Any, **Any.

@dhruvmanila dhruvmanila merged commit 58d5fe9 into main Mar 13, 2025
22 checks passed
@dhruvmanila dhruvmanila deleted the dhruv/callable-is-gradual-equivalent-to branch March 13, 2025 02:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants