pyre-check icon indicating copy to clipboard operation
pyre-check copied to clipboard

Pyre doesn't understand that metaclass instances are classes

Open xmo-odoo opened this issue 5 years ago • 2 comments

class Meta(type):
    ...


# class C1: ...
C1 = type("C1", (object,), {})
class C12(C1):
     ...

# class C2(metaclass=Meta): ...
C2 = Meta("C2", (object,), {})
class C22(C2):
    ...

but Pyre rejects this with

Undefined or invalid type [11]: Annotation <X> is not defined as a type.

xmo-odoo avatar Oct 13 '20 11:10 xmo-odoo

This is impossible to support in general -- what you are trying to do here is to dynamically create a class and then subclass it, which is very hostile toward static type checking. For example, Pyre cannot figure out what attributes are there for C1 and C2 since the dict can be computed at runtime if you construct the type with type or metaclasses.

grievejia avatar Oct 16 '20 16:10 grievejia

@grievejia I completely agree for the general case, but the code in question is literally this, entirely static.

Now you might be wondering why the hell we'd be using such a construct statically, and the reason is P2/P3 compatibility (which we have not removed yet): per PEP 3115 Python 3 ignores __metaclass__ class-level attributes, but the metaclass class keyword is a syntax error in P2, so the call-the-metaclass trick is the only way to use metaclasses in a cross-version codebase.

And TBF pyre could still infer that the result of instantiating a metaclass is a type, even if it's opaque / unknown.

xmo-odoo avatar Oct 19 '20 05:10 xmo-odoo