Unexpected (to me) Divergent type manifesting in isinstance()
Summary
Consider the following example:
class Foo: ...
if isinstance(123, "Foo"):
pass
This example is obviously ill-formed, but what is interesting about it is the diagnostic that ty emits:
error[invalid-argument-type]: Argument to function `isinstance` is incorrect
--> divergent.py:3:20
|
1 | class Foo: ...
2 |
3 | if isinstance(123, "Foo"):
| ^^^^^ Expected `type | UnionType | tuple[Divergent, ...]`, found `Literal["Foo"]`
4 | pass
|
info: Function defined here
--> stdlib/builtins.pyi:3768:5
|
3766 | _ClassInfo: TypeAlias = type | tuple[_ClassInfo, ...]
3767 |
3768 | def isinstance(obj: object, class_or_tuple: _ClassInfo, /) -> bool:
| ^^^^^^^^^^ -------------------------- Parameter declared here
3769 | """Return whether an object is an instance of a class or of a subclass thereof.
|
info: rule `invalid-argument-type` is enabled by default
I am not sure the intention of this, but I would not expect a Divergent to appear in visible user output.
Version
ty 0.0.7
Thanks for reporting this. It seems that the root issue is lack of support for self-referential generic implicit/PEP-613 type aliases (https://github.com/astral-sh/ty/issues/1738).
In general, it is definitely possible for Divergent to appear in visible user output, in cases where there is recursion that doesn't converge.
In this particular case, this Divergent should go away once #1738 is fixed. The root cause is that the _ClassInfo type alias in typeshed is recursive.