Skip to content

Unable to type __subclasses__ #835

@rwarren

Description

@rwarren

Describe the bug

I have a case where I introspect through classes with __subclasses__, and I can't get pyrefly to manage typing properly. Here is a reduced case:

In the simplest case I want pyrefly to just infer types without me telling it anything, but I get errors:

class Bottom: pass

class Mid1(Bottom): pass
class Mid2(Bottom): pass

class Top1(Mid1): pass
class Top2(Mid1): pass
class Top3(Mid2): pass

for mid in Bottom.__subclasses__():   # <-- Pyrefly(bad-argument-type) (see below)
    for top in mid.__subclasses__():  # <--- Object of class `TypeVar` has no attribute `__subclasses__` Pyrefly(missing-attribute)
        print(top.__name__)

... where that bad-argument-type" is Argument type is not assignable to parameter self with type TypeVar[Self] in function `type.subclasses``.

If I try and type those loop vars explicitly I get different errors:

class Bottom: pass

class Mid1(Bottom): pass
class Mid2(Bottom): pass

class Top1(Mid1): pass
class Top2(Mid1): pass
class Top3(Mid2): pass

mid: type[Bottom]
for mid in Bottom.__subclasses__():   # <-- Cannot use variable `mid` with type `type[Bottom]` to iterate through `list[TypeVar[Self]]` Pyrefly(bad-assignment)
    top: type[Mid1 | Mid2]
    for top in mid.__subclasses__():  # <-- Cannot use variable `top` with type `type[Mid1 | Mid2]` to iterate through `list[TypeVar[Self]]`Pyrefly(bad-assignment)
        print(top.__name__)

This does seem to be a bit of a tricky case, since both mypy and pyright have varying issues as well:

  • both mypy and pyright are 100% ok with the no-hints approach of the first example (no warnings or errors)
  • In the second example, mypy does complain with this in the inner for loop:
    • Incompatible types in assignment (expression has type "type[Bottom]", variable has type "type[Mid1] | type[Mid2]")
  • In the second example, pyright (via pylance) complains about the top assignment with this:
Type "type[Bottom]" is not assignable to declared type "type[Mid1] | type[Mid2]"
  Type "type[Bottom]" is not assignable to type "type[Mid1] | type[Mid2]"
    "type[Bottom]" is not assignable to "type[Mid1]"
    Type "type[Bottom]" is not assignable to type "type[Mid1]"
    "type[Bottom]" is not assignable to "type[Mid2]"
    Type "type[Bottom]" is not assignable to type "type[Mid2]" Pylance[reportAssignmentType](https://github.com/microsoft/pylance-release/blob/main/docs/diagnostics/reportAssignmentType.md)
(variable) top: type[Mid1] | type[Mid2]

VERSIONS

Relevant versions are:

  • python: 3.11.13
  • pyrefly vscode extension: 0.26.1
  • vscode: 1.102.3

Sandbox Link

https://pyrefly.org/sandbox/?code=MYGwhgzhAEBCD2AXR8C2AuaAHSEBQeou0AsgJYAmAjABQLJoCUmOUh4UplATHUiqmbZcBIpwAq8LLXLUhrfGJiSsvWVXkil0FQGYas7prZ5UlTIgCeWAKYBtegIC6eAGbwATtDMVoZAHZw-GgAdAD6YRAArgBGSjYQETTMeNBp0ChYFtb26tAAPlwU3C7p0O5emX6BPuGRsfGJYcnoqWXpWB4BiDSZdf5gqDYRjHhAA

(Only applicable for extension issues) IDE Information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions