Skip to content

Should overloaded function to ParamSpec work with argument type expansion? #2568

@dhruvmanila

Description

@dhruvmanila

In astral-sh/ruff#21946, there's a test case which ty passes but other type checkers raise an error:

from typing import Callable, overload

@overload
def int_int(x: int) -> int: ...
@overload
def int_int(x: str) -> int: ...

def with_parameters[**P](f: Callable[P, int], *args: P.args, **kwargs: P.kwargs) -> Callable[P, str]:
    def nested(*args: P.args, **kwargs: P.kwargs) -> str:
        return str(f(*args, **kwargs))
    return nested

def foo(int_or_str: int | str):
    # Argument type expansion leads to matching both overloads.
    # TODO: Should this be an error instead?
    # revealed: Overload[(x: int) -> str, (x: str) -> str]
    reveal_type(with_parameters(int_int, int_or_str))

Other type checkers emit a diagnostic here:

I'm not exactly sure why do other type checkers emit a diagnostic here, maybe there's an unsoundness argument to this behavior?

Metadata

Metadata

Assignees

No one assigned

    Labels

    callsIssues relating to call-signature checking and diagnosticsneeds-decisionAwaiting a decision from a maintaineroverloads

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions