Skip to content

overloaded __new__ ignored when introducing __init__ #17251

@jakkdl

Description

@jakkdl

Bug Report
I'm hitting a problem where the return type of an overloaded __new__ is ignored once an __init__ is added. I've searched the issue tracker thoroughly and while I've found a ton of issues related to __new__ return types I haven't found one that seems to be the same thing.

To Reproduce

from __future__ import annotations

from typing import (
    Any,
    Generic,
    TypeVar,
    overload,
)

BE = TypeVar("BE", bound=BaseException)
E = TypeVar("E", bound=Exception)


class MyBaseClass(Generic[BE]):
    @overload
    def __new__(cls, arg: type[E]) -> MyClass[E]:
        ...
    @overload
    def __new__(cls, arg: type[BE]) -> MyBaseClass[BE]:
        ...

    def __new__(cls, arg: Any) -> Any:
        if issubclass(arg, Exception):
            return MyClass(arg)
        return MyBaseClass(arg)

    def __init__(self, arg: type[BE]):  # pyright: ignore[reportInconsistentConstructor]
        self.arg = arg

class MyClass(MyBaseClass[E]):
    def __init__(self, arg: type[E]):  # pyright: ignore[reportInconsistentConstructor]
        self.arg = arg


reveal_type(MyBaseClass(ValueError))
reveal_type(MyBaseClass(KeyboardInterrupt))

I've also found it ~impossible to type the signatures for the __new__ and __init__ implementation, but that's a separate issue.

Actual Behavior

$  mypy foo.py                                             
foo.py:36: note: Revealed type is "foo.MyBaseClass[builtins.ValueError]"
foo.py:37: note: Revealed type is "foo.MyBaseClass[builtins.KeyboardInterrupt]"

pyright handles it without issue.

$ pyright foo.py
  ./foo.py:36:13 - information: Type of "MyBaseClass(ValueError)" is "MyClass[ValueError]"
  ./foo.py:37:13 - information: Type of "MyBaseClass(KeyboardInterrupt)" is "MyBaseClass[KeyboardInterrupt]" 

and if I remove the __init__ from MyBaseClass then mypy handles the overloads correctly:

$  mypy foo.py
foo.py:36: note: Revealed type is "foo.MyClass[builtins.ValueError]"
foo.py:37: note: Revealed type is "foo.MyBaseClass[builtins.KeyboardInterrupt]"
Success: no issues found in 1 source file

Your Environment

  • Mypy version used: 1.10.0
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.11.8

The source of the problem is trying to improve the typing of trio.testing.RaisesGroup: python-trio/trio#2989

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions