Skip to content

(馃巵) Perform 'union math' on non overloaded calls聽#13493

Open

Description

@KotlinIsland

Here the call to f is distributing the generic over the return type (based), but the call to the standalone function can't be resolved

from typing import Iterable, overload, TypeVar

a: list[int] | list[str]

@overload
def f[T](i: list[T]) -> list[T]: ...
@overload
def f() -> None: ...
def f[T](i: list[T] = []) -> list[T] | None: ...

reveal_type(f(a))  # list[int] | list[str]

def g[T](i: list[T]) -> list[T]: return []

reveal_type(g(a))  # error: Cannot infer type argument 1 of "g"  [misc]

playground

What's happening here is that union_overload_result, which is intended for when a call with a union would match multiple overload parts, is matching twice against the same overload, resulting is a more accurate return type.

Activity

  1. changed the title [-](馃悶) Generics behave differently on overloads compared to single functions[/-] [+](馃巵) Perform 'union math' on non overloaded calls[/+] on Aug 24, 2022
  2. ilevkivskyi commented on Feb 9, 2025

    @ilevkivskyi
    Member

    Both examples now infer this:

    Revealed type is "builtins.list[Union[builtins.int, builtins.str]]"
    

    But this is by accident, because in your example T = int | str is a valid solution for T even without union math. But in general I agree that we may want to use union math more eagerly if it results in a more precise type.

  3. KotlinIsland commented on Feb 19, 2025

    @KotlinIsland
    ContributorAuthor

    i updated the op

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions