UPDATE: This might be fixed. I can repro with 0.62.0 and Python 3.11.15, but not in the sandbox. I'm not sure how to tell what commit the sandbox is running. Apologies if this is obvious and I missed it.
Describe the Bug
Description
When a covariant generic class H[_T_co] has a concrete __init__ overload typed as self: H[int] / init_val: int, and a function accepts H[CanAdd[_AddWithT, _ResultT]] (a two-TypeVar protocol), pyrefly raises no-matching-overload on the bare constructor call H(10).
The call should be semantically valid:
H(10) resolves to H[int] via the int overload.
int structurally satisfies CanAdd[int, int]
(int.__add__(int) -> int).
- Because
_T_co is covariant, H[int] is a subtype of
H[CanAdd[int, int]].
- Type-variable unification therefore yields
_AddWithT = int,
_ResultT = int, and the return type is H[int].
mypy (--strict), pyright, and ty all accept this code without errors.
The error message itself also seems misleading: pyrefly blames H.__init__ for not accepting Literal[10], but Literal[10] is obviously a subtype of int. The real issue appears to be that pyrefly propagates the expected type H[CanAdd[...]] backwards into overload selection before solving the free TypeVars, finds no overload whose self annotation exactly matches H[CanAdd[...]], and raises the error at the inner H(10) constructor rather than at the outer explode_n call.
Versions
pyrefly 0.62.0 → 1 error
mypy 1.x --strict → 0 errors
pyright → 0 errors
ty → 0 errors
from typing import Generic, Never, Protocol, TypeVar, overload
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_AddWithT_contra = TypeVar("_AddWithT_contra", contravariant=True)
_ResultT_co = TypeVar("_ResultT_co", covariant=True)
_AddWithT = TypeVar("_AddWithT")
_ResultT = TypeVar("_ResultT")
class CanAdd(Protocol[_AddWithT_contra, _ResultT_co]):
def __add__(self, other: _AddWithT_contra, /) -> _ResultT_co: ...
class H(Generic[_T_co]):
@overload
def __init__(self: "H[Never]", init_val: dict[Never, int], /) -> None: ...
@overload
def __init__(self: "H[_T]", init_val: dict[_T, int], /) -> None: ...
@overload
def __init__(self: "H[int]", init_val: int, /) -> None: ...
def __init__(self, init_val: object, /) -> None: ...
def explode_n(source: "H[CanAdd[_AddWithT, _ResultT]]") -> "H[_ResultT]":
raise NotImplementedError
# pyrefly 0.62.0 raises:
# ERROR No matching overload found for function `H.__init__`
# called with arguments: (Literal[10]) [no-matching-overload]
# mypy --strict, pyright, ty: no errors
result: "H[int]" = explode_n(H(10))
Sandbox Link
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0BxGOhiUIAYwA0dAHIwAbqOkAFag1zjcUaQBVmMAGqpK03IspRcqTAB10dgPo66AXjp7ih4wAobIJ34AlI46Dpqu7vpGlL7%2BoZp%2B0pryxhAYDC46lACuMMHoDgCCmJgA6hAMABbxuOgMlKgRHl4xfkUl5VU1dQ2JdJo9qCli6Zk5eY4ASvDZUAw1TVE%2BbdNws-NhuH3JqaNZufntZRXVi57RsUed1UFTM3PObs0XK-fzt-bo4lCocHB0AGEMMVMN5VLh1JooABtK4nbr1VDSByrdY1AC6gUQdjouLomBgYDoDgc1kwJO8cBgUDApiqokQxJB1wRDWkAHpAnQALQAPmJqIem0ZhFFdjs31%2B-wAEt4hCIxOJYRisTi8QABMyiSzWNW4glEkmsCoUqk0xl%2BaXQuTmdF9Y0MBwpKCMzASBjWhRKTh1dEcrl82S1GAisXoPF0TXmHW2cN4g3EhwO03UsAWkBWpx2kDSZPO13u5W533%2Bnn8mTB0OEPWRrUWKyxiMJo3oE0OSmp9NW1gMbPFk35n0MUuBisiKs15tJ1uO9tm2k%2BgeoF10XDYABWMHEw7onLLQfHdFF1c%2BCZg%2BGIlgJDnQlNw2Uo4hDdEt0KB6BBsOZ8ORgvm6OzAN%2BVfFE3h0bNsTjXEGggKkgwYABJbhYBoYQGBgTAAFFKGoShxXQABiOgyEoQkoFIOgAAZCAANgAJkISi6Bgqk4EgojcUwyZJgAeUmIM6BoVAGHESpWA4OsYzoMB7ywaTeGk7IvgYCBajoAADaVCBbNt1LsDiIzxcRl1gTA6AAdxOOhjDYbJULqNi6G8AAZCpRGXaEAEZKMxOhoXQXBuSEkSxPYblJIbO1CME5gKO5bk4Hqd1pBIiA2EqHcmEZAK6FEXC4DsUi1jmLtoR7bMInPS9cGvW9ZW8wJAhzEASLI0hCHUGgoAoIjlFIUiwHIug0CwPB8H6WpIFshoVNqE8iIAZRgGA6AyhhiDY9l2Vawb2t4Nh2WEdlMA0OB2QGKaH2E1T0HZeTKGslJoFQbBYAm9BLpmm7V2IWb0DgE8yCqWpuXMOBvrcPwAGZCE8ui-DsaE8t4OAoqUrgeD4DDuTdUjtwgRQIgAcjSgLSKJuwAoYblSIAR2yCBSMwbkAGsYFIblUHEJ8-mJ8zjHQCn0BAABfSQQC5lTFAAMWgGAKBGnACBIcgRaAA
(Only applicable for extension issues) IDE Information
No response
UPDATE: This might be fixed. I can repro with 0.62.0 and Python 3.11.15, but not in the sandbox. I'm not sure how to tell what commit the sandbox is running. Apologies if this is obvious and I missed it.
Describe the Bug
Description
When a covariant generic class
H[_T_co]has a concrete__init__overload typed asself: H[int]/init_val: int, and a function acceptsH[CanAdd[_AddWithT, _ResultT]](a two-TypeVar protocol), pyrefly raisesno-matching-overloadon the bare constructor callH(10).The call should be semantically valid:
H(10)resolves toH[int]via theintoverload.intstructurally satisfiesCanAdd[int, int](
int.__add__(int) -> int)._T_cois covariant,H[int]is a subtype ofH[CanAdd[int, int]]._AddWithT = int,_ResultT = int, and the return type isH[int].mypy (
--strict), pyright, and ty all accept this code without errors.The error message itself also seems misleading: pyrefly blames
H.__init__for not acceptingLiteral[10], butLiteral[10]is obviously a subtype ofint. The real issue appears to be that pyrefly propagates the expected typeH[CanAdd[...]]backwards into overload selection before solving the free TypeVars, finds no overload whoseselfannotation exactly matchesH[CanAdd[...]], and raises the error at the innerH(10)constructor rather than at the outerexplode_ncall.Versions
pyrefly 0.62.0 → 1 error
mypy 1.x --strict → 0 errors
pyright → 0 errors
ty → 0 errors
Sandbox Link
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0BxGOhiUIAYwA0dAHIwAbqOkAFag1zjcUaQBVmMAGqpK03IspRcqTAB10dgPo66AXjp7ih4wAobIJ34AlI46Dpqu7vpGlL7%2BoZp%2B0pryxhAYDC46lACuMMHoDgCCmJgA6hAMABbxuOgMlKgRHl4xfkUl5VU1dQ2JdJo9qCli6Zk5eY4ASvDZUAw1TVE%2BbdNws-NhuH3JqaNZufntZRXVi57RsUed1UFTM3PObs0XK-fzt-bo4lCocHB0AGEMMVMN5VLh1JooABtK4nbr1VDSByrdY1AC6gUQdjouLomBgYDoDgc1kwJO8cBgUDApiqokQxJB1wRDWkAHpAnQALQAPmJqIem0ZhFFdjs31%2B-wAEt4hCIxOJYRisTi8QABMyiSzWNW4glEkmsCoUqk0xl%2BaXQuTmdF9Y0MBwpKCMzASBjWhRKTh1dEcrl82S1GAisXoPF0TXmHW2cN4g3EhwO03UsAWkBWpx2kDSZPO13u5W533%2Bnn8mTB0OEPWRrUWKyxiMJo3oE0OSmp9NW1gMbPFk35n0MUuBisiKs15tJ1uO9tm2k%2BgeoF10XDYABWMHEw7onLLQfHdFF1c%2BCZg%2BGIlgJDnQlNw2Uo4hDdEt0KB6BBsOZ8ORgvm6OzAN%2BVfFE3h0bNsTjXEGggKkgwYABJbhYBoYQGBgTAAFFKGoShxXQABiOgyEoQkoFIOgAAZCAANgAJkISi6Bgqk4EgojcUwyZJgAeUmIM6BoVAGHESpWA4OsYzoMB7ywaTeGk7IvgYCBajoAADaVCBbNt1LsDiIzxcRl1gTA6AAdxOOhjDYbJULqNi6G8AAZCpRGXaEAEZKMxOhoXQXBuSEkSxPYblJIbO1CME5gKO5bk4Hqd1pBIiA2EqHcmEZAK6FEXC4DsUi1jmLtoR7bMInPS9cGvW9ZW8wJAhzEASLI0hCHUGgoAoIjlFIUiwHIug0CwPB8H6WpIFshoVNqE8iIAZRgGA6AyhhiDY9l2Vawb2t4Nh2WEdlMA0OB2QGKaH2E1T0HZeTKGslJoFQbBYAm9BLpmm7V2IWb0DgE8yCqWpuXMOBvrcPwAGZCE8ui-DsaE8t4OAoqUrgeD4DDuTdUjtwgRQIgAcjSgLSKJuwAoYblSIAR2yCBSMwbkAGsYFIblUHEJ8-mJ8zjHQCn0BAABfSQQC5lTFAAMWgGAKBGnACBIcgRaAA
(Only applicable for extension issues) IDE Information
No response