Skip to content

Unknown inferred when solving generic overloaded calls involving invariant generics specialized with Any #2979

@AlexWaygood

Description

@AlexWaygood

Summary

Observe: the first reveal_type shows us solving the type variables correctly, but for the second reveal_type, not only do we fail to solve the type variables, we fallback to Unknown for the whole type!

from typing import Any, overload, reveal_type

class Invariant[KT, VT]:
    attr2: VT

    @overload
    def foo(self, other: Invariant[KT, VT]) -> Invariant[KT, VT]: ...
    @overload
    def foo[T1, T2](self, other: Invariant[T1, T2]) -> Invariant[KT | T1, VT | T2]: ...
    def foo(self, other):
        raise NotImplementedError

def g(x: Invariant[int, int], y: Invariant[int, str], z: Invariant[int, Any]):
    reveal_type(x.foo(y))  # Invariant[int, int | str]
    
    reveal_type(x.foo(z))  # ty: Unknown
                           # pycroscope: Any[multiple_overload_matches]
                           # mypy, zuban: Invariant[Any, Any]
                           # pyrefly, pyright: Invariant[int, int]

This comes up in the real world with dict.__or__ in typeshed:

https://github.com/astral-sh/ruff/blob/546d3b2b1ad214976c5238174efcb061df548207/crates/ty_vendored/vendor/typeshed/stdlib/builtins.pyi#L3056-L3061

Meaning:

reveal_type({"foo": "bar"} | {})  # Unknown

Multiplay gist comparing our inference with other type checkers: 0685f09832604c2cb53928d004881454.

Version

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggenericsBugs or features relating to ty's generics implementationoverloads

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions