Skip to content

Prefer generic overload with matching positional-only parameters over *args: Any overload #1809

@sharkdp

Description

@sharkdp

Consider the following example, and notice how we currently infer Unknown for the call to f(1, 2). This only happens if the (*args: Any) -> tuple[Any, ...] overload is also present, so I assume that the Unknown is caused by the fact that we can't eliminate all but one overload in the first stage of overload matching here, and then need to consider two overloads during typevar solving:

from typing import overload, Any, reveal_type

@overload
def f[T](x: T, /) -> tuple[T]: ...
@overload
def f[T1, T2](x1: T1, x2: T2, /) -> tuple[T1, T2]: ...
@overload
def f(*args: Any) -> tuple[Any, ...]: ...
def f(*args: Any) -> tuple[Any, ...]:
    raise NotImplementedError

reveal_type(f(1))  # tuple[Literal[1]]
reveal_type(f(1, 2))  # Unknown
reveal_type(f(1, 2, 3))  # tuple[Any, ...]

What's also interesting is that we correctly infer tuple[Literal[1], Literal[1]] for a call to f(1, 1), i.e. if T1 and T2 solve to the same type.

Metadata

Metadata

Assignees

Labels

genericsBugs or features relating to ty's generics implementationoverloads

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions