Repository: python/mypy
Pull request: Honor return type of `__new__`
This basically follows the approach Jukka laid out in #1020 four years ago:
 * If the return type is Any, ignore that and keep the class type as
   the return type
 * Otherwise respect `__new__`'s return type
 * Produce an error if the return type is not a subtype of the class.

The main motivation for me in implementing this is to support
overloading `__new__` in order to select type variable arguments,
which will be useful for subprocess.Popen.

Fixes #1020.

Problem statement:
Honor return type of `__new__`
Currently the return type of `A(...)` is implicitly `A` even if `A.__new__` return something else. If the return type is `Any`, maybe `A(...)` should have type `Any`, and if it's a subclass, we should also use that. Currently this is a little difficult to implement due to implementation limitations (we derive the type object identity from the return type of a type object). Maybe we should introduce a new attribute to `Callable` for this purpose.

Hints from issue discussion:
This is follow-up to #982.

Honestly I don't think that `A()` should ever return something that's not an instance of A (or a subclass), even though technically `__new__()` can return anything it likes. Somehow I worry that if `__new__()` were defined as returning Any for some class and from that we'd infer that `A()` returned Any we would weaken the type checking -- I'd much rather get an error if the declared return type of `__new__()` isn't A or a subclass of A.

Have you seen any real code that violates this rule?

No, I haven't seen real code that uses this, but I've seen tutorials that mention that this is possible -- they always mention that you probably shouldn't do that. 

Okay, what about this:
- If the return type is `Any` (either implicit or explicit), we don't check return statements within `__new__` but the type of `A()` is still `A`.
- If the return type of `__new__` is not `A` or a subclass of `A` (and not `Any`), reject it as a type error.
- If the return type `B` is a proper subclass of `A`, `A()` has type `B`.

SGTM

@JukkaL On one hand, constructor returning an instance of different class is unacceptable in static typed languages. But on other hand, this feature is sometimes quite useful in Python. Even `typing.py` uses this for `Union` and for `NamedTuple` (since 3.6b1).

In general, it would be nice if mypy minimizes the number of false positives like flagging this code:

``` python
class C:
    def __new__(cls):
        return 0

C() + 1
```

with `Unsupported operand types for + ("C" and "int")`. Maybe there could be an option to allow this.

One thought: the return type of `__new__`, if explicitly defined and different from the class name itself, could implicitly be the class's supertype.

```python
class ZeroLiteral:  # supertype: int
    def __new__(cls) -> int:
        return 0
```

This would also be a general alternative to https://github.com/python/typing/issues/415 and could likely handle https://github.com/python/mypy/issues/3062
We make use of `__new__` to promote base classes to leaf classes in a few places.  I don't love it, but it'll take some serious effort to untangle it, so I'm gonna +1 this for the case of base class promoting to subclasses.

Ours works something like this:

```python
from typing import Union

class Base(object):
    def __init__(self, name):
        self.name = name

    def __new__(cls, name):
        # type: (str) -> Union[A, B]
        if cls is Base:
            if name == 'A':
                return A(name)
            else:
                return B(name)
        else:
            # A or B
            return object.__new__(cls)

class A(Base):
    pass

class B(Base):
    pass

b = Base('B')
reveal_type(b)
```

The revealed type is `Base`, but I expect it to `Union[A, B]`.

Also, this seems related to #3307.


Another use case that I had is to have async constructor, poor man's \_\_ainit__:
```python
class WorkItem(metaclass=ABCMeta):
    async def __new__(cls, *args, **kwargs):
        """ Override __new__ to support our custom `async` constructors. """
        o = super().__new__(cls)
        await o.ainit(*args, **kwargs)
        return o
```

That actually fails in a different place, as in this case __new__ returns the right thing, but 

```python
class BuildItem(WorkItem):    ...
toolsetItem = await BuildItem(...)
```

fails with:
> error: Incompatible types in "await" (actual type "BuildItem", expected type "Awaitable[Any]")
Another (less controversial) use case is at least to honor the return type of `__new__` for generics, see https://github.com/python/mypy/issues/4236#issuecomment-416076433

Commit message: Honor return type of `__new__`

This basically follows the approach Jukka laid out in #1020 four years ago:
 * If the return type is Any, ignore that and keep the class type as
   the return type
 * Otherwise respect `__new__`'s return type
 * Produce an error if the return type is not a subtype of the class.

The main motivation for me in implementing this is to support
overloading `__new__` in order to select type variable arguments,
which will be useful for subprocess.Popen.

Fixes #1020.

Patch to review:
diff --git a/mypy/checker.py b/mypy/checker.py
index 9f1c348cf528..569a4994c2bb 100644
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -803,6 +803,10 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str])
                         self.fail(message_registry.MUST_HAVE_NONE_RETURN_TYPE.format(fdef.name()),
                                   item)
 
+                    # Check validity of __new__ signature
+                    if fdef.info and fdef.name() == '__new__':
+                        self.check___new___signature(fdef, typ)
+
                     self.check_for_missing_annotations(fdef)
                     if self.options.disallow_any_unimported:
                         if fdef.type and isinstance(fdef.type, CallableType):
@@ -1015,6 +1019,27 @@ def is_unannotated_any(t: Type) -> bool:
                 if any(is_unannotated_any(t) for t in fdef.type.arg_types):
                     self.fail(message_registry.ARGUMENT_TYPE_EXPECTED, fdef)
 
+    def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None:
+        self_type = fill_typevars_with_any(fdef.info)
+        bound_type = bind_self(typ, self_type, is_classmethod=True)
+        # Check that __new__ (after binding cls) returns an instance
+        # type (or any)
+        if not isinstance(bound_type.ret_type, (AnyType, Instance, TupleType)):
+            self.fail(
+                message_registry.NON_INSTANCE_NEW_TYPE.format(
+                    self.msg.format(bound_type.ret_type)),
+                fdef)
+        else:
+            # And that it returns a subtype of the class
+            self.check_subtype(
+                bound_type.ret_type,
+                self_type,
+                fdef,
+                message_registry.INVALID_NEW_TYPE,
+                'returns',
+                'but must return a subtype of'
+            )
+
     def is_trivial_body(self, block: Block) -> bool:
         """Returns 'true' if the given body is "trivial" -- if it contains just a "pass",
         "..." (ellipsis), or "raise NotImplementedError()". A trivial body may also
diff --git a/mypy/checkmember.py b/mypy/checkmember.py
index 31696633bca0..ad34fca90bcb 100644
--- a/mypy/checkmember.py
+++ b/mypy/checkmember.py
@@ -803,8 +803,10 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) ->
     fallback = info.metaclass_type or builtin_type('builtins.type')
     if init_index < new_index:
         method = init_method.node  # type: Union[FuncBase, Decorator]
+        is_new = False
     elif init_index > new_index:
         method = new_method.node
+        is_new = True
     else:
         if init_method.node.info.fullname() == 'builtins.object':
             # Both are defined by object.  But if we've got a bogus
@@ -823,6 +825,7 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) ->
         # is the right thing, but __new__ caused problems with
         # typeshed (#5647).
         method = init_method.node
+        is_new = False
     # Construct callable type based on signature of __init__. Adjust
     # return type and insert type arguments.
     if isinstance(method, FuncBase):
@@ -830,7 +833,7 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) ->
     else:
         assert isinstance(method.type, FunctionLike)  # is_valid_constructor() ensures this
         t = method.type
-    return type_object_type_from_function(t, info, method.info, fallback)
+    return type_object_type_from_function(t, info, method.info, fallback, is_new)
 
 
 def is_valid_constructor(n: Optional[SymbolNode]) -> bool:
@@ -849,7 +852,8 @@ def is_valid_constructor(n: Optional[SymbolNode]) -> bool:
 def type_object_type_from_function(signature: FunctionLike,
                                    info: TypeInfo,
                                    def_info: TypeInfo,
-                                   fallback: Instance) -> FunctionLike:
+                                   fallback: Instance,
+                                   is_new: bool) -> FunctionLike:
     # The __init__ method might come from a generic superclass
     # (init_or_new.info) with type variables that do not map
     # identically to the type variables of the class being constructed
@@ -859,7 +863,7 @@ def type_object_type_from_function(signature: FunctionLike,
     #   class B(A[List[T]], Generic[T]): pass
     #
     # We need to first map B's __init__ to the type (List[T]) -> None.
-    signature = bind_self(signature)
+    signature = bind_self(signature, original_type=fill_typevars(info), is_classmethod=is_new)
     signature = cast(FunctionLike,
                      map_type_from_supertype(signature, info, def_info))
     special_sig = None  # type: Optional[str]
@@ -868,25 +872,32 @@ def type_object_type_from_function(signature: FunctionLike,
         special_sig = 'dict'
 
     if isinstance(signature, CallableType):
-        return class_callable(signature, info, fallback, special_sig)
+        return class_callable(signature, info, fallback, special_sig, is_new)
     else:
         # Overloaded __init__/__new__.
         assert isinstance(signature, Overloaded)
         items = []  # type: List[CallableType]
         for item in signature.items():
-            items.append(class_callable(item, info, fallback, special_sig))
+            items.append(class_callable(item, info, fallback, special_sig, is_new))
         return Overloaded(items)
 
 
 def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance,
-                   special_sig: Optional[str]) -> CallableType:
+                   special_sig: Optional[str],
+                   is_new: bool = False) -> CallableType:
     """Create a type object type based on the signature of __init__."""
     variables = []  # type: List[TypeVarDef]
     variables.extend(info.defn.type_vars)
     variables.extend(init_type.variables)
 
+    is_new = True
+    if is_new and isinstance(init_type.ret_type, (Instance, TupleType)):
+        ret_type = init_type.ret_type  # type: Type
+    else:
+        ret_type = fill_typevars(info)
+
     callable_type = init_type.copy_modified(
-        ret_type=fill_typevars(info), fallback=type_type, name=None, variables=variables,
+        ret_type=ret_type, fallback=type_type, name=None, variables=variables,
         special_sig=special_sig)
     c = callable_type.with_name(info.name())
     return c
diff --git a/mypy/interpreted_plugin.py b/mypy/interpreted_plugin.py
index 5306b8927156..ae83bc816cf0 100644
--- a/mypy/interpreted_plugin.py
+++ b/mypy/interpreted_plugin.py
@@ -22,7 +22,8 @@ class InterpretedPlugin:
     that proxies to this interpreted version.
     """
 
-    def __new__(cls, *args: Any, **kwargs: Any) -> 'mypy.plugin.Plugin':
+    # ... mypy doesn't like these shenanigans so we have to type ignore it!
+    def __new__(cls, *args: Any, **kwargs: Any) -> 'mypy.plugin.Plugin':  # type: ignore
         from mypy.plugin import WrapperPlugin
         plugin = object.__new__(cls)
         plugin.__init__(*args, **kwargs)
diff --git a/mypy/message_registry.py b/mypy/message_registry.py
index 3e08d54a18dd..bb1c72c25b66 100644
--- a/mypy/message_registry.py
+++ b/mypy/message_registry.py
@@ -51,6 +51,8 @@
 INVALID_SLICE_INDEX = 'Slice index must be an integer or None'  # type: Final
 CANNOT_INFER_LAMBDA_TYPE = 'Cannot infer type of lambda'  # type: Final
 CANNOT_ACCESS_INIT = 'Cannot access "__init__" directly'  # type: Final
+NON_INSTANCE_NEW_TYPE = '"__new__" must return a class instance (got {})'  # type: Final
+INVALID_NEW_TYPE = 'Incompatible return type for "__new__"'  # type: Final
 BAD_CONSTRUCTOR_TYPE = 'Unsupported decorated constructor type'  # type: Final
 CANNOT_ASSIGN_TO_METHOD = 'Cannot assign to a method'  # type: Final
 CANNOT_ASSIGN_TO_TYPE = 'Cannot assign to a type'  # type: Final
diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test
index fb6aa73fcf66..38e60f45f50c 100644
--- a/test-data/unit/check-class-namedtuple.test
+++ b/test-data/unit/check-class-namedtuple.test
@@ -598,7 +598,7 @@ class XMethBad(NamedTuple):
 class MagicalFields(NamedTuple):
     x: int
     def __slots__(self) -> None: pass  # E: Cannot overwrite NamedTuple attribute "__slots__"
-    def __new__(cls) -> None: pass  # E: Cannot overwrite NamedTuple attribute "__new__"
+    def __new__(cls) -> MagicalFields: pass  # E: Cannot overwrite NamedTuple attribute "__new__"
     def _source(self) -> int: pass  # E: Cannot overwrite NamedTuple attribute "_source"
     __annotations__ = {'x': float}  # E: NamedTuple field name cannot start with an underscore: __annotations__ \
         # E: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" \
diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test
index 334f02571cf2..9a113ace0df1 100644
--- a/test-data/unit/check-classes.test
+++ b/test-data/unit/check-classes.test
@@ -344,12 +344,12 @@ main:6: error: Return type "A" of "f" incompatible with return type "None" in su
 
 [case testOverride__new__WithDifferentSignature]
 class A:
-    def __new__(cls, x: int) -> str:
-        return ''
+    def __new__(cls, x: int) -> A:
+        pass
 
 class B(A):
-    def __new__(cls) -> int:
-        return 1
+    def __new__(cls) -> B:
+        pass
 
 [case testOverride__new__AndCallObject]
 from typing import TypeVar, Generic
@@ -5363,8 +5363,8 @@ class A:
         pass
 
 class B(A):
-    def __new__(cls) -> int:
-        return 10
+    def __new__(cls) -> B:
+        pass
 
 B()
 
@@ -5975,3 +5975,105 @@ class E(C):
         reveal_type(self.x) # N: Revealed type is 'builtins.int'
 
 [targets __main__, __main__, __main__.D.g, __main__.D.f, __main__.C.__init__, __main__.E.g, __main__.E.f]
+
+[case testNewReturnType1]
+class A:
+    def __new__(cls) -> B:
+        pass
+
+class B(A): pass
+
+reveal_type(A())  # N: Revealed type is '__main__.B'
+reveal_type(B())  # N: Revealed type is '__main__.B'
+
+[case testNewReturnType2]
+from typing import Any
+
+# make sure that __new__ method that return Any are ignored when
+# determining the return type
+class A:
+    def __new__(cls):
+        pass
+
+class B:
+    def __new__(cls) -> Any:
+        pass
+
+reveal_type(A())  # N: Revealed type is '__main__.A'
+reveal_type(B())  # N: Revealed type is '__main__.B'
+
+[case testNewReturnType3]
+
+# Check for invalid __new__ typing
+
+class A:
+    def __new__(cls) -> int:  # E: Incompatible return type for "__new__" (returns "int", but must return a subtype of "A")
+        pass
+
+reveal_type(A())  # N: Revealed type is 'builtins.int'
+
+[case testNewReturnType4]
+from typing import TypeVar, Type
+
+# Check for __new__ using type vars
+
+TX = TypeVar('TX', bound='X')
+class X:
+    def __new__(lol: Type[TX], x: int) -> TX:
+        pass
+class Y(X): pass
+
+reveal_type(X(20))  # N: Revealed type is '__main__.X*'
+reveal_type(Y(20))  # N: Revealed type is '__main__.Y*'
+
+[case testNewReturnType5]
+from typing import Any, TypeVar, Generic, overload
+
+T = TypeVar('T')
+class O(Generic[T]):
+    @overload
+    def __new__(cls) -> O[int]:
+        pass
+    @overload
+    def __new__(cls, x: int) -> O[str]:
+        pass
+    def __new__(cls, x: int = 0) -> O[Any]:
+        pass
+
+reveal_type(O())  # N: Revealed type is '__main__.O[builtins.int]'
+reveal_type(O(10))  # N: Revealed type is '__main__.O[builtins.str]'
+
+[case testNewReturnType6]
+from typing import Tuple, Optional
+
+# Check for some cases that aren't allowed
+
+class X:
+    def __new__(cls) -> Optional[Y]:  # E: "__new__" must return a class instance (got "Optional[Y]")
+        pass
+class Y:
+    def __new__(cls) -> Optional[int]:  # E: "__new__" must return a class instance (got "Optional[int]")
+        pass
+
+
+[case testNewReturnType7]
+from typing import NamedTuple
+
+# ... test __new__ returning tuple type
+class A:
+    def __new__(cls) -> 'B':
+        pass
+
+N = NamedTuple('N', [('x', int)])
+class B(A, N): pass
+
+reveal_type(A())  # N: Revealed type is 'Tuple[builtins.int, fallback=__main__.B]'
+
+[case testNewReturnType8]
+from typing import TypeVar, Any
+
+# test type var from a different argument
+TX = TypeVar('TX', bound='X')
+class X:
+    def __new__(cls, x: TX) -> TX:  # E: "__new__" must return a class instance (got "TX")
+        pass
diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test
index 9f015f24986c..d61ce527fd35 100644
--- a/test-data/unit/check-enum.test
+++ b/test-data/unit/check-enum.test
@@ -6,7 +6,7 @@ class Medal(Enum):
     gold = 1
     silver = 2
     bronze = 3
-reveal_type(Medal.bronze)  # N: Revealed type is '__main__.Medal'
+reveal_type(Medal.bronze)  # N: Revealed type is '__main__.Medal*'
 m = Medal.gold
 if int():
     m = 1  # E: Incompatible types in assignment (expression has type "int", variable has type "Medal")
@@ -167,7 +167,7 @@ class E(IntEnum):
 x = None  # type: int
 reveal_type(E(x))
 [out]
-main:5: note: Revealed type is '__main__.E'
+main:5: note: Revealed type is '__main__.E*'
 
 [case testEnumIndex]
 from enum import IntEnum
@@ -246,7 +246,7 @@ class A:
 a = A()
 reveal_type(a.x)
 [out]
-main:8: note: Revealed type is '__main__.E@4'
+main:8: note: Revealed type is '__main__.E@4*'
 
 [case testEnumInClassBody]
 from enum import Enum
@@ -270,9 +270,9 @@ reveal_type(E.bar.value)
 reveal_type(I.bar)
 reveal_type(I.baz.value)
 [out]
-main:4: note: Revealed type is '__main__.E'
+main:4: note: Revealed type is '__main__.E*'
 main:5: note: Revealed type is 'Any'
-main:6: note: Revealed type is '__main__.I'
+main:6: note: Revealed type is '__main__.I*'
 main:7: note: Revealed type is 'builtins.int'
 
 [case testFunctionalEnumListOfStrings]
@@ -282,8 +282,8 @@ F = IntEnum('F', ['bar', 'baz'])
 reveal_type(E.foo)
 reveal_type(F.baz)
 [out]
-main:4: note: Revealed type is '__main__.E'
-main:5: note: Revealed type is '__main__.F'
+main:4: note: Revealed type is '__main__.E*'
+main:5: note: Revealed type is '__main__.F*'
 
 [case testFunctionalEnumListOfPairs]
 from enum import Enum, IntEnum
@@ -294,8 +294,8 @@ reveal_type(F.baz)
 reveal_type(E.foo.value)
 reveal_type(F.bar.name)
 [out]
-main:4: note: Revealed type is '__main__.E'
-main:5: note: Revealed type is '__main__.F'
+main:4: note: Revealed type is '__main__.E*'
+main:5: note: Revealed type is '__main__.F*'
 main:6: note: Revealed type is 'builtins.int'
 main:7: note: Revealed type is 'builtins.str'
 
@@ -308,8 +308,8 @@ reveal_type(F.baz)
 reveal_type(E.foo.value)
 reveal_type(F.bar.name)
 [out]
-main:4: note: Revealed type is '__main__.E'
-main:5: note: Revealed type is '__main__.F'
+main:4: note: Revealed type is '__main__.E*'
+main:5: note: Revealed type is '__main__.F*'
 main:6: note: Revealed type is 'builtins.int'
 main:7: note: Revealed type is 'builtins.str'
 
@@ -363,8 +363,8 @@ main:22: error: "Type[W]" has no attribute "c"
 from enum import Flag, IntFlag
 A = Flag('A', 'x y')
 B = IntFlag('B', 'a b')
-reveal_type(A.x)        # N: Revealed type is '__main__.A'
-reveal_type(B.a)        # N: Revealed type is '__main__.B'
+reveal_type(A.x)        # N: Revealed type is '__main__.A*'
+reveal_type(B.a)        # N: Revealed type is '__main__.B*'
 reveal_type(A.x.name)   # N: Revealed type is 'builtins.str'
 reveal_type(B.a.name)   # N: Revealed type is 'builtins.str'
 
@@ -381,7 +381,7 @@ class A:
 a = A()
 reveal_type(a.x)
 [out]
-main:7: note: Revealed type is '__main__.A.E@4'
+main:7: note: Revealed type is '__main__.A.E@4*'
 
 [case testFunctionalEnumInClassBody]
 from enum import Enum
@@ -451,11 +451,11 @@ F = Enum('F', 'a b')
 [rechecked]
 [stale]
 [out1]
-main:2: note: Revealed type is 'm.E'
-main:3: note: Revealed type is 'm.F'
+main:2: note: Revealed type is 'm.E*'
+main:3: note: Revealed type is 'm.F*'
 [out2]
-main:2: note: Revealed type is 'm.E'
-main:3: note: Revealed type is 'm.F'
+main:2: note: Revealed type is 'm.E*'
+main:3: note: Revealed type is 'm.F*'
 
 [case testEnumAuto]
 from enum import Enum, auto
@@ -463,7 +463,7 @@ class Test(Enum):
     a = auto()
     b = auto()
 
-reveal_type(Test.a)  # N: Revealed type is '__main__.Test'
+reveal_type(Test.a)  # N: Revealed type is '__main__.Test*'
 [builtins fixtures/primitives.pyi]
 
 [case testEnumAttributeAccessMatrix]
@@ -689,31 +689,31 @@ else:
 
 if x is z:
     reveal_type(x)  # N: Revealed type is 'Literal[__main__.Foo.A]'
-    reveal_type(z)  # N: Revealed type is '__main__.Foo'
+    reveal_type(z)  # N: Revealed type is '__main__.Foo*'
     accepts_foo_a(z)
 else:
     reveal_type(x)  # N: Revealed type is 'Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]'
-    reveal_type(z)  # N: Revealed type is '__main__.Foo'
+    reveal_type(z)  # N: Revealed type is '__main__.Foo*'
     accepts_foo_a(z)
 if z is x:
     reveal_type(x)  # N: Revealed type is 'Literal[__main__.Foo.A]'
-    reveal_type(z)  # N: Revealed type is '__main__.Foo'
+    reveal_type(z)  # N: Revealed type is '__main__.Foo*'
     accepts_foo_a(z)
 else:
     reveal_type(x)  # N: Revealed type is 'Union[Literal[__main__.Foo.B], Literal[__main__.Foo.C]]'
-    reveal_type(z)  # N: Revealed type is '__main__.Foo'
+    reveal_type(z)  # N: Revealed type is '__main__.Foo*'
     accepts_foo_a(z)
 
 if y is z:
     reveal_type(y)  # N: Revealed type is 'Literal[__main__.Foo.A]'
-    reveal_type(z)  # N: Revealed type is '__main__.Foo'
+    reveal_type(z)  # N: Revealed type is '__main__.Foo*'
     accepts_foo_a(z)
 else:
     reveal_type(y)  # No output: this branch is unreachable
     reveal_type(z)  # No output: this branch is unreachable
 if z is y:
     reveal_type(y)  # N: Revealed type is 'Literal[__main__.Foo.A]'
-    reveal_type(z)  # N: Revealed type is '__main__.Foo'
+    reveal_type(z)  # N: Revealed type is '__main__.Foo*'
     accepts_foo_a(z)
 else:
     reveal_type(y)  # No output: this branch is unreachable
diff --git a/test-data/unit/check-final.test b/test-data/unit/check-final.test
index f3fad1daf25f..26e25ff00348 100644
--- a/test-data/unit/check-final.test
+++ b/test-data/unit/check-final.test
@@ -797,7 +797,7 @@ class B:
     def __new__(cls) -> B: ...
 class C(B):
     def __init__(self) -> None: ...  # E: Cannot override final attribute "__init__" (previously declared in base class "B")
-    def __new__(cls) -> B: ...  # E: Cannot override final attribute "__new__" (previously declared in base class "B")
+    def __new__(cls) -> C: ...  # E: Cannot override final attribute "__new__" (previously declared in base class "B")
 [out]
 
 [case testFinalOverridingMethodWithVar]
diff --git a/test-data/unit/check-super.test b/test-data/unit/check-super.test
index 31398f9ff835..e8c1a2721e58 100644
--- a/test-data/unit/check-super.test
+++ b/test-data/unit/check-super.test
@@ -85,9 +85,10 @@ class A:
         return object.__new__(cls)
 
 class B(A):
-    def __new__(cls, x: int, y: str = '') -> 'A':
+    def __new__(cls, x: int, y: str = '') -> 'B':
         super().__new__(cls, 1)
-        return super().__new__(cls, 1, '')  # E: Too many arguments for "__new__" of "A"
+        super().__new__(cls, 1, '')  # E: Too many arguments for "__new__" of "A"
+        return None
 B('')  # E: Argument 1 to "B" has incompatible type "str"; expected "int"
 B(1)
 B(1, 'x')
diff --git a/test-data/unit/python2eval.test b/test-data/unit/python2eval.test
index 8e808122f09f..2267cadb1a08 100644
--- a/test-data/unit/python2eval.test
+++ b/test-data/unit/python2eval.test
@@ -303,7 +303,7 @@ print 4j / 2.0
 from typing import Dict, Any
 class MyType(type):
     def __new__(cls, name, bases, namespace):
-        # type: (str, tuple, Dict[str, Any]) -> type
+        # type: (str, tuple, Dict[str, Any]) -> Any
         return super(MyType, cls).__new__(cls, name + 'x', bases, namespace)
 class A(object):
     __metaclass__ = MyType
diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test
index fbfa379163c3..ecd98aeb5e68 100644
--- a/test-data/unit/pythoneval.test
+++ b/test-data/unit/pythoneval.test
@@ -692,7 +692,7 @@ _program.py:6: error: Incompatible types in assignment (expression has type "str
 [case testSuperNew]
 from typing import Dict, Any
 class MyType(type):
-    def __new__(cls, name: str, bases: tuple, namespace: Dict[str, Any]) -> type:
+    def __new__(cls, name: str, bases: tuple, namespace: Dict[str, Any]) -> Any:
         return super().__new__(cls, name + 'x', bases, namespace)
 class A(metaclass=MyType): pass
 print(type(A()).__name__)
@@ -912,8 +912,10 @@ class A:
 _program.py:4: error: Argument 1 to "__setattr__" of "object" has incompatible type "int"; expected "str"
 
 [case testMetaclassAndSuper]
+from typing import Any
+
 class A(type):
-    def __new__(cls, name, bases, namespace) -> 'type':
+    def __new__(cls, name, bases, namespace) -> Any:
         return super().__new__(cls, '', (object,), {'x': 7})
 
 class B(metaclass=A):


Code review comments:
diff_hunk: @@ -868,25 +872,32 @@ def type_object_type_from_function(signature: FunctionLike,
         special_sig = 'dict'
 
     if isinstance(signature, CallableType):
-        return class_callable(signature, info, fallback, special_sig)
+        return class_callable(signature, info, fallback, special_sig, is_new)
     else:
         # Overloaded __init__/__new__.
         assert isinstance(signature, Overloaded)
         items = []  # type: List[CallableType]
         for item in signature.items():
-            items.append(class_callable(item, info, fallback, special_sig))
+            items.append(class_callable(item, info, fallback, special_sig, is_new))
         return Overloaded(items)
 
 
 def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance,
-                   special_sig: Optional[str]) -> CallableType:
+                   special_sig: Optional[str],
+                   is_new: bool = False) -> CallableType:
     """Create a type object type based on the signature of __init__."""
     variables = []  # type: List[TypeVarDef]
     variables.extend(info.defn.type_vars)
     variables.extend(init_type.variables)
 
+    is_new = True
path: mypy/checkmember.py
text: @user1:
This looks suspicious for two reasons:
* You unconditionally override an argument with an opposite default.
* Just below it appears in an `if`

@author:
Oh hm. That was testing code that survived because it works without it, since NoneTyp won't trigger the isinstance check...