pyre-check
pyre-check copied to clipboard
Pyre doesn't understand that metaclass instances are classes
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.
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 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.