ruff
2ddadb99 - [ty] Fix constructor calls on narrowed type-variable intersections (#27493)

Commit
30 days ago
[ty] Fix constructor calls on narrowed type-variable intersections (#27493) ## Summary In #27449, we start treating calls to `type[object]` strictly (using `object.__init__` rather than the overly forgiving `type.__call__`). This also means that `type[T] & type[SomeType]` intersections (which can easily arise with a parameter `cls: type[T]` which is then narrowed via `issubclass(cls, SomeType)`) start validating the `type[T]` portion against `object.__init__` (assuming `T` has no upper bound besides `object`). That means if the call to `type[SomeType]` fails, we now get confusing double diagnostics also complaining about the failed call to `object.__init__`. This PR resolves that problem separately in a general way: if we have an intersection `type[T] & type[SomeClass]`, where `SomeClass` is a subclass of the upper bound of `T`, we don't try calling both constructors; we just try the constructor of `SomeClass`. (But we preserve the full intersection as receiver, so that the result of the call will still be `T & SomeClass`, not just `SomeClass`.) Since all classes are subclasses of `object`, this means we don't try calling `object.__init__` or emit errors about it when they are redundant and confusing in an intersection with some more specific `type[...]`. (This is only relevant to intersections with `type[T]` where `T` is a typevar, since a normal `type[Base] & type[Child]` intersection would immediately simplify to `type[Child]`. That simplification doesn't occur with a typevar, since we need to preserve the typevar identity; it may actually represent a narrower type, not its upper bound.) - Resolve constructor calls on narrowed `type[T] & type[Child]` intersections using the applicable subclass constructor instead of treating the type-variable bound as an independent alternative. - Preserve the precise `T & Child` result, report only subclass-constructor argument errors, and retain specialized generic constructors, built-in behavior, independent metaclass callables, and explicit `__new__` / metaclass `__call__` return types. ## Test plan - Added constructor mdtests for `issubclass`-narrowed bounded, constrained, and unbounded type variables; valid return types; rejected arguments; and deduplicated diagnostics. - Covered explicitly specialized generic constructors, literal-preserving built-in constructors, `Self` returns, non-instance `__new__` and metaclass `__call__` returns, and intersections with independent metaclass callables. Ecosystem changes are both correct/improvements.
Author
Parents
Loading