Skip to content

Explore alternate implementation for callable type equivalence #165

@dhruvmanila

Description

@dhruvmanila

Currently, the general callable type uses a manual implementation to check whether the two types are equivalent (is_equivalent_to). This is required for two reasons:

  1. The type of the default values don't participate in checking for equivalence, it's only the optionality that participates i.e., is the parameter required for both callable types or not?
  2. The name of positional-only, variadic and keyword-variadic parameters don't participate in checking for equivalence

Refer to astral-sh/ruff#16698 (comment) for previous discussion.

A possible option that's discussed in the above thread is to erase the information that doesn't participate in equivalence relation (above two points) when constructing a GeneralCallableType from a function literal. This will mean that we can remove the manual implementation and it will then use the catch-all branch:

https://github.com/astral-sh/ruff/blob/3b1e030fbbe586a2b8918d4f1c33cea710faa446/crates/red_knot_python_semantic/src/types.rs#L913-L913

This has the benefit that the equivalence is maintained at the type level. But, this does mean that (a) we'll need to make name: Name into name: Option<Name> to erase it or replace it with Name("") (empty name seems error prone) and (b) use something else for the default type as Type::Unknown is not a static type, maybe just replace it with None.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type propertiessubtyping, assignability, equivalence, and more

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions