Skip to content

Commit 8b3d25a

Browse files
committed
Fix inference for properties with __call__
1 parent 5af7671 commit 8b3d25a

File tree

1 file changed

+37
-37
lines changed

1 file changed

+37
-37
lines changed

mypy/checkmember.py

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -779,44 +779,44 @@ def analyze_var(
779779
if (
780780
var.is_initialized_in_class
781781
and (not is_instance_var(var) or mx.is_operator)
782-
and isinstance(typ, FunctionLike)
783-
and not typ.is_type_obj()
784782
):
785-
if mx.is_lvalue:
786-
if var.is_property:
787-
if not var.is_settable_property:
788-
mx.msg.read_only_property(name, itype.type, mx.context)
789-
else:
790-
mx.msg.cant_assign_to_method(mx.context)
791-
792-
if not var.is_staticmethod:
793-
# Class-level function objects and classmethods become bound methods:
794-
# the former to the instance, the latter to the class.
795-
functype = typ
796-
# Use meet to narrow original_type to the dispatched type.
797-
# For example, assume
798-
# * A.f: Callable[[A1], None] where A1 <: A (maybe A1 == A)
799-
# * B.f: Callable[[B1], None] where B1 <: B (maybe B1 == B)
800-
# * x: Union[A1, B1]
801-
# In `x.f`, when checking `x` against A1 we assume x is compatible with A
802-
# and similarly for B1 when checking against B
803-
dispatched_type = meet.meet_types(mx.original_type, itype)
804-
signature = freshen_all_functions_type_vars(functype)
805-
bound = get_proper_type(expand_self_type(var, signature, mx.original_type))
806-
assert isinstance(bound, FunctionLike)
807-
signature = bound
808-
signature = check_self_arg(
809-
signature, dispatched_type, var.is_classmethod, mx.context, name, mx.msg
810-
)
811-
signature = bind_self(signature, mx.self_type, var.is_classmethod)
812-
expanded_signature = expand_type_by_instance(signature, itype)
813-
freeze_all_type_vars(expanded_signature)
814-
if var.is_property:
815-
# A property cannot have an overloaded type => the cast is fine.
816-
assert isinstance(expanded_signature, CallableType)
817-
result = expanded_signature.ret_type
818-
else:
819-
result = expanded_signature
783+
call_type = _analyze_member_access("__call__", typ, mx)
784+
if isinstance(call_type, FunctionLike) and not call_type.is_type_obj():
785+
if mx.is_lvalue:
786+
if var.is_property:
787+
if not var.is_settable_property:
788+
mx.msg.read_only_property(name, itype.type, mx.context)
789+
else:
790+
mx.msg.cant_assign_to_method(mx.context)
791+
792+
if not var.is_staticmethod:
793+
# Class-level function objects and classmethods become bound methods:
794+
# the former to the instance, the latter to the class.
795+
functype = call_type
796+
# Use meet to narrow original_type to the dispatched type.
797+
# For example, assume
798+
# * A.f: Callable[[A1], None] where A1 <: A (maybe A1 == A)
799+
# * B.f: Callable[[B1], None] where B1 <: B (maybe B1 == B)
800+
# * x: Union[A1, B1]
801+
# In `x.f`, when checking `x` against A1 we assume x is compatible with A
802+
# and similarly for B1 when checking against B
803+
dispatched_type = meet.meet_types(mx.original_type, itype)
804+
signature = freshen_all_functions_type_vars(functype)
805+
bound = get_proper_type(expand_self_type(var, signature, mx.original_type))
806+
assert isinstance(bound, FunctionLike)
807+
signature = bound
808+
signature = check_self_arg(
809+
signature, dispatched_type, var.is_classmethod, mx.context, name, mx.msg
810+
)
811+
signature = bind_self(signature, mx.self_type, var.is_classmethod)
812+
expanded_signature = expand_type_by_instance(signature, itype)
813+
freeze_all_type_vars(expanded_signature)
814+
if var.is_property:
815+
# A property cannot have an overloaded type => the cast is fine.
816+
assert isinstance(expanded_signature, CallableType)
817+
result = expanded_signature.ret_type
818+
else:
819+
result = expanded_signature
820820
else:
821821
if not var.is_ready and not mx.no_deferral:
822822
mx.not_ready_callback(var.name, mx.context)

0 commit comments

Comments
 (0)