Describe the Bug
When a class with a @dataclass_transform()-decorated metaclass declares def __new__(cls, ...) -> "Base", pyrefly types every subclass instance as the base class instead of the concrete subclass.
This results in the following problems:
- Subclass-specific methods (including
__call__) are not visible, the expression subclass_instance(...) raises not-callable.
- Functions parameterised on an intermediate abstract subclass reject calls with concrete subclasses (
bad-argument-type).
- Attributes defined only on the subclass are reported as missing.
I hit this when using equinox which uses this pattern in its base class:
@dataclass_transform(field_specifiers=(...))
class Meta(BaseMeta):
def __call__(cls, *args: object, **kwargs: object): ...
class Module(Hashable, metaclass=Meta):
def __new__(cls, *args: object, **kwargs: object) -> "Module": # <-- here
...
Pyrefly typed every Subclass(...) as Module, generating dozens of spurious not-callable / bad-argument-type errors in unrelated files.
Minimal Reproducer
from typing_extensions import dataclass_transform
@dataclass_transform()
class Meta(type):
pass
class Base(metaclass=Meta):
def __new__(cls, *args: object, **kwargs: object) -> "Base":
return super().__new__(cls)
class Greeter(Base):
name: str
def __call__(self, greeting: str) -> str:
return self.name
g = Greeter(name="world")
out: str = g("hello") # pyrefly: Expected a callable, got `Base`
Pyrefly output (1.0.0)
ERROR Expected a callable, got `Base` [not-callable]
Pyright output
Notes
- Removing
@dataclass_transform() makes pyright and pyrefly agree (both say Base). The bug is in the interaction between dataclass_transform and the literal-string -> "Base" return on __new__.
Sandbox Link
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOYD6M%2BDM6cEXPzoQaxXJQZ1MqBqgDGUVHDgcGlDHDASaAHXT6AAjLmLlq9Zu2UaACgCU%2BsyroBZGHNtNiMe4n10gXTE5vpOSi4AQsowtjQeChFwALzucn4BQZgwYHQcHOgwAO75topwADR0AFSolGxwiHS42ABWMPIMVdXVANZFdQ1NLe2d9nQAtAB8dLog0XAwc-7oQWt0lB4ArpSrcFs%2BlA6E%2BYUlHGVQcI4G6M5wdADimx4wRwu%2BK2voqPFNcOpMoFsrl8vJUFAoKVFlAwFU2C8GKw2P91ONpnQAZQvutApsGDs9jBYYQfvEwuw6Mknoi3rYyTBknMihIoJg5jdcFsGKjKFS6GxbHMABbEqC4DlBADEwVImzAUFITQAovgfJ0YJg6Kg6ODIahsLB4bgpAADD6mkAVEBkeWKwgMWhQCgygAKcpyisxGBwBF1QkgbB2skE6EI%2BhlAGUYDA6MKGAxiI0APTJ22e0iECRsZN8ZOYXDyODJ%2BQBiBBjRIoTJujWbUAN1Q0ANsH96EDwarq1wxC7cHD6DIDGFQgm9beAiE-LmAGZCABGABMc30AG03tRKHAALr6LboUTiSSaiaYCCbToQcf8gDk5fQEhgN-0D4YE02AEctueT70YKQJgUeR4AeakbwGXZn3QEAAF9rQUJFxwAMWgGAKDQLA8CIMhYKAA
(Only applicable for extension issues) IDE Information
No response
Describe the Bug
When a class with a
@dataclass_transform()-decorated metaclass declaresdef __new__(cls, ...) -> "Base", pyrefly types every subclass instance as the base class instead of the concrete subclass.This results in the following problems:
__call__) are not visible, the expressionsubclass_instance(...)raisesnot-callable.bad-argument-type).I hit this when using
equinoxwhich uses this pattern in its base class:Pyrefly typed every
Subclass(...)asModule, generating dozens of spuriousnot-callable/bad-argument-typeerrors in unrelated files.Minimal Reproducer
Pyrefly output (1.0.0)
Pyright output
Notes
@dataclass_transform()makes pyright and pyrefly agree (both sayBase). The bug is in the interaction betweendataclass_transformand the literal-string-> "Base"return on__new__.Sandbox Link
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOYD6M%2BDM6cEXPzoQaxXJQZ1MqBqgDGUVHDgcGlDHDASaAHXT6AAjLmLlq9Zu2UaACgCU%2BsyroBZGHNtNiMe4n10gXTE5vpOSi4AQsowtjQeChFwALzucn4BQZgwYHQcHOgwAO75topwADR0AFSolGxwiHS42ABWMPIMVdXVANZFdQ1NLe2d9nQAtAB8dLog0XAwc-7oQWt0lB4ArpSrcFs%2BlA6E%2BYUlHGVQcI4G6M5wdADimx4wRwu%2BK2voqPFNcOpMoFsrl8vJUFAoKVFlAwFU2C8GKw2P91ONpnQAZQvutApsGDs9jBYYQfvEwuw6Mknoi3rYyTBknMihIoJg5jdcFsGKjKFS6GxbHMABbEqC4DlBADEwVImzAUFITQAovgfJ0YJg6Kg6ODIahsLB4bgpAADD6mkAVEBkeWKwgMWhQCgygAKcpyisxGBwBF1QkgbB2skE6EI%2BhlAGUYDA6MKGAxiI0APTJ22e0iECRsZN8ZOYXDyODJ%2BQBiBBjRIoTJujWbUAN1Q0ANsH96EDwarq1wxC7cHD6DIDGFQgm9beAiE-LmAGZCABGABMc30AG03tRKHAALr6LboUTiSSaiaYCCbToQcf8gDk5fQEhgN-0D4YE02AEctueT70YKQJgUeR4AeakbwGXZn3QEAAF9rQUJFxwAMWgGAKDQLA8CIMhYKAA
(Only applicable for extension issues) IDE Information
No response