Skip to content

Commit c4dcdaa

Browse files
committed
Fix various type object handling
Fixes most of #12320. I didn't add tests for every code path because it's niche. I also didn't fix everything, in particular the cases where we proceed to use `ret_type`, or ones I thought were scary
1 parent ff81a1c commit c4dcdaa

File tree

6 files changed

+19
-10
lines changed

6 files changed

+19
-10
lines changed

mypy/checker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2986,7 +2986,7 @@ def check_assignment(
29862986
p_rvalue_type = get_proper_type(rvalue_type)
29872987
p_lvalue_type = get_proper_type(lvalue_type)
29882988
if (
2989-
isinstance(p_rvalue_type, CallableType)
2989+
isinstance(p_rvalue_type, FunctionLike)
29902990
and p_rvalue_type.is_type_obj()
29912991
and (
29922992
p_rvalue_type.type_object().is_abstract
@@ -3771,7 +3771,7 @@ def split_around_star(
37713771

37723772
def type_is_iterable(self, type: Type) -> bool:
37733773
type = get_proper_type(type)
3774-
if isinstance(type, CallableType) and type.is_type_obj():
3774+
if isinstance(type, FunctionLike) and type.is_type_obj():
37753775
type = type.fallback
37763776
return is_subtype(
37773777
type, self.named_generic_type("typing.Iterable", [AnyType(TypeOfAny.special_form)])

mypy/checkexpr.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ def check_runtime_protocol_test(self, e: CallExpr) -> None:
694694
for expr in mypy.checker.flatten(e.args[1]):
695695
tp = get_proper_type(self.chk.lookup_type(expr))
696696
if (
697-
isinstance(tp, CallableType)
697+
isinstance(tp, FunctionLike)
698698
and tp.is_type_obj()
699699
and tp.type_object().is_protocol
700700
and not tp.type_object().runtime_protocol
@@ -704,7 +704,7 @@ def check_runtime_protocol_test(self, e: CallExpr) -> None:
704704
def check_protocol_issubclass(self, e: CallExpr) -> None:
705705
for expr in mypy.checker.flatten(e.args[1]):
706706
tp = get_proper_type(self.chk.lookup_type(expr))
707-
if isinstance(tp, CallableType) and tp.is_type_obj() and tp.type_object().is_protocol:
707+
if isinstance(tp, FunctionLike) and tp.is_type_obj() and tp.type_object().is_protocol:
708708
attr_members = non_method_protocol_members(tp.type_object())
709709
if attr_members:
710710
self.chk.msg.report_non_method_protocol(tp.type_object(), attr_members, e)
@@ -4142,7 +4142,7 @@ def visit_index_with_type(
41424142
elif isinstance(left_type, TypedDictType):
41434143
return self.visit_typeddict_index_expr(left_type, e.index)
41444144
elif (
4145-
isinstance(left_type, CallableType)
4145+
isinstance(left_type, FunctionLike)
41464146
and left_type.is_type_obj()
41474147
and left_type.type_object().is_enum
41484148
):
@@ -5721,7 +5721,7 @@ def has_abstract_type_part(self, caller_type: ProperType, callee_type: ProperTyp
57215721

57225722
def has_abstract_type(self, caller_type: ProperType, callee_type: ProperType) -> bool:
57235723
return (
5724-
isinstance(caller_type, CallableType)
5724+
isinstance(caller_type, FunctionLike)
57255725
and isinstance(callee_type, TypeType)
57265726
and caller_type.is_type_obj()
57275727
and (caller_type.type_object().is_abstract or caller_type.type_object().is_protocol)

mypy/messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def has_no_attr(
411411
elif member == "__getitem__":
412412
# Indexed get.
413413
# TODO: Fix this consistently in format_type
414-
if isinstance(original_type, CallableType) and original_type.is_type_obj():
414+
if isinstance(original_type, FunctionLike) and original_type.is_type_obj():
415415
self.fail(
416416
"The type {} is not generic and not indexable".format(
417417
format_type(original_type, self.options)

mypy/plugins/proper_plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def is_dangerous_target(typ: ProperType) -> bool:
131131
"""Is this a dangerous target (right argument) for an isinstance() check?"""
132132
if isinstance(typ, TupleType):
133133
return any(is_dangerous_target(get_proper_type(t)) for t in typ.items)
134-
if isinstance(typ, CallableType) and typ.is_type_obj():
134+
if isinstance(typ, FunctionLike) and typ.is_type_obj():
135135
return typ.type_object().has_base("mypy.types.Type")
136136
return False
137137

mypy/typeops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ def custom_special_method(typ: Type, name: str, check_all: bool = False) -> bool
989989
return any(custom_special_method(t, name) for t in typ.items)
990990
if isinstance(typ, TupleType):
991991
return custom_special_method(tuple_fallback(typ), name, check_all)
992-
if isinstance(typ, CallableType) and typ.is_type_obj():
992+
if isinstance(typ, FunctionLike) and typ.is_type_obj():
993993
# Look up __method__ on the metaclass for class objects.
994994
return custom_special_method(typ.fallback, name, check_all)
995995
if isinstance(typ, AnyType):

test-data/unit/check-abstract.test

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ f(GoodAlias)
241241

242242
[case testInstantiationAbstractsInTypeForVariables]
243243
# flags: --no-strict-optional
244-
from typing import Type
244+
from typing import Type, overload
245245
from abc import abstractmethod
246246

247247
class A:
@@ -269,6 +269,15 @@ if int():
269269
var_old = B # E: Can only assign concrete classes to a variable of type "Type[A]"
270270
if int():
271271
var_old = C # OK
272+
273+
class D(A):
274+
@overload
275+
def __new__(cls, a) -> "D": ...
276+
@overload
277+
def __new__(cls) -> "D": ...
278+
def __new__(cls, a=None) -> "D": ...
279+
if int():
280+
var = D # E: Can only assign concrete classes to a variable of type "Type[A]"
272281
[out]
273282

274283
[case testInstantiationAbstractsInTypeForClassMethods]

0 commit comments

Comments
 (0)