Skip to content

Commit

Permalink
Only return a declared type from __new__ if it is a subtype of the cl…
Browse files Browse the repository at this point in the history
…ass (#7656)

Fixes #7597.
  • Loading branch information
msullivan committed Oct 9, 2019
1 parent 6f8480c commit c95ecc1
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
15 changes: 12 additions & 3 deletions mypy/typeops.py
Expand Up @@ -77,11 +77,20 @@ def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance,
variables.extend(info.defn.type_vars)
variables.extend(init_type.variables)

from mypy.subtypes import is_subtype

init_ret_type = get_proper_type(init_type.ret_type)
if is_new and isinstance(init_ret_type, (Instance, TupleType)):
ret_type = init_type.ret_type # type: Type
default_ret_type = fill_typevars(info)
if (
is_new
and isinstance(init_ret_type, (Instance, TupleType))
# Only use the return type from __new__ if it is actually returning
# a subtype of what we would return otherwise.
and is_subtype(init_ret_type, default_ret_type, ignore_type_params=True)
):
ret_type = init_ret_type # type: Type
else:
ret_type = fill_typevars(info)
ret_type = default_ret_type

callable_type = init_type.copy_modified(
ret_type=ret_type, fallback=type_type, name=None, variables=variables,
Expand Down
12 changes: 11 additions & 1 deletion test-data/unit/check-classes.test
Expand Up @@ -6031,7 +6031,7 @@ 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'
reveal_type(A()) # N: Revealed type is '__main__.A'

[case testNewReturnType4]
from typing import TypeVar, Type
Expand Down Expand Up @@ -6099,6 +6099,16 @@ class X:
def __new__(cls, x: TX) -> TX: # E: "__new__" must return a class instance (got "TX")
pass

[case testNewReturnType9]
class A:
def __new__(cls) -> A:
pass

class B(A):
pass

reveal_type(B()) # N: Revealed type is '__main__.B'

[case testGenericOverride]
from typing import Generic, TypeVar, Any

Expand Down

0 comments on commit c95ecc1

Please sign in to comment.