Skip to content

Callable[[T1 | T2], ...] parameter causes generic arguments to collapse to unions #3203

Description

@pwuertz

Summary

ty appears to incorrectly widen independent generic parameters when a function accepts a Callable with a union-typed parameter, like

def foo[T1, T2](t1: T1, t2: T2, f: Callable[[T1 | T2], None]): ...

Both T1 and T2 are widened to T1 | T2, apparently caused by the presence of the Callable. For reference, this doesn't happen if the third argument is a simple T1 | T2 value, or a list[T1 | T2].

Reproducer

In the example below, T1 and T2 should cleanly map to X1 and X2, but ty infers both as X1 | X2:

import typing
from collections.abc import Callable

class X1: ...
class X2: ...

def foo[T1, T2](
    t1: T1,
    t2: T2,
    f: Callable[[T1 | T2], None],
) -> tuple[T1, T2]:
    f(t1), f(t2)
    return t1, t2

def fx(_: X1 | X2) -> None: ...

result = foo(X1(), X2(), fx)
typing.assert_type(result, tuple[X1, X2])

# ty 0.0.27
# error[type-assertion-failure]: Argument does not have asserted type `tuple[X1, X2]`
# Inferred type is `tuple[X1 | X2, X2 | X1]`

Maybe related

This may be related to #2799?

Version

ty 0.0.27

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions