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
Summary
Observe: the first
reveal_typeshows us solving the type variables correctly, but for the secondreveal_type, not only do we fail to solve the type variables, we fallback toUnknownfor the whole type!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:
Multiplay gist comparing our inference with other type checkers: 0685f09832604c2cb53928d004881454.
Version
No response