4242 erase_to_bound ,
4343 freeze_all_type_vars ,
4444 function_type ,
45+ get_all_type_vars ,
4546 get_type_vars ,
4647 make_simplified_union ,
4748 supported_self_type ,
@@ -606,7 +607,10 @@ def analyze_member_var_access(
606607 setattr_meth = info .get_method ("__setattr__" )
607608 if setattr_meth and setattr_meth .info .fullname != "builtins.object" :
608609 bound_type = analyze_decorator_or_funcbase_access (
609- defn = setattr_meth , itype = itype , name = name , mx = mx .copy_modified (is_lvalue = False )
610+ defn = setattr_meth ,
611+ itype = itype ,
612+ name = "__setattr__" ,
613+ mx = mx .copy_modified (is_lvalue = False ),
610614 )
611615 typ = map_instance_to_supertype (itype , setattr_meth .info )
612616 setattr_type = get_proper_type (expand_type_by_instance (bound_type , typ ))
@@ -872,15 +876,13 @@ def analyze_var(
872876 mx .msg .read_only_property (name , itype .type , mx .context )
873877 if var .is_classvar :
874878 mx .msg .cant_assign_to_classvar (name , mx .context )
875- t = freshen_all_functions_type_vars (typ )
876- t = expand_self_type_if_needed (t , mx , var , original_itype )
877- t = expand_type_by_instance (t , itype )
878- freeze_all_type_vars (t )
879- result = t
880- typ = get_proper_type (typ )
879+ # This is the most common case for variables, so start with this.
880+ result = expand_without_binding (typ , var , itype , original_itype , mx )
881881
882+ # A non-None value indicates that we should actually bind self for this variable.
882883 call_type : ProperType | None = None
883884 if var .is_initialized_in_class and (not is_instance_var (var ) or mx .is_operator ):
885+ typ = get_proper_type (typ )
884886 if isinstance (typ , FunctionLike ) and not typ .is_type_obj ():
885887 call_type = typ
886888 elif var .is_property :
@@ -890,37 +892,23 @@ def analyze_var(
890892 else :
891893 call_type = typ
892894
895+ # Bound variables with callable types are treated like methods
896+ # (these are usually method aliases like __rmul__ = __mul__).
893897 if isinstance (call_type , FunctionLike ) and not call_type .is_type_obj ():
894- if mx .is_lvalue and not mx .suppress_errors :
895- if var .is_property and not var .is_settable_property :
896- mx .msg .read_only_property (name , itype .type , mx .context )
897- elif not var .is_property :
898- mx .msg .cant_assign_to_method (mx .context )
899-
900- if not var .is_staticmethod :
901- # Class-level function objects and classmethods become bound methods:
902- # the former to the instance, the latter to the class.
903- functype : FunctionLike = call_type
904- signature = freshen_all_functions_type_vars (functype )
905- bound = get_proper_type (expand_self_type (var , signature , mx .original_type ))
906- assert isinstance (bound , FunctionLike )
907- signature = bound
908- signature = check_self_arg (
909- signature , mx .self_type , var .is_classmethod , mx .context , name , mx .msg
910- )
911- signature = bind_self (signature , mx .self_type , var .is_classmethod )
912- expanded_signature = expand_type_by_instance (signature , itype )
913- freeze_all_type_vars (expanded_signature )
914- if var .is_property :
915- # A property cannot have an overloaded type => the cast is fine.
916- assert isinstance (expanded_signature , CallableType )
917- if var .is_settable_property and mx .is_lvalue and var .setter_type is not None :
918- # TODO: use check_call() to infer better type, same as for __set__().
919- result = expanded_signature .arg_types [0 ]
920- else :
921- result = expanded_signature .ret_type
898+ if mx .is_lvalue and not var .is_property and not mx .suppress_errors :
899+ mx .msg .cant_assign_to_method (mx .context )
900+
901+ # Bind the self type for each callable component (when needed).
902+ if call_type and not var .is_staticmethod :
903+ bound_items = []
904+ for ct in call_type .items if isinstance (call_type , UnionType ) else [call_type ]:
905+ p_ct = get_proper_type (ct )
906+ if isinstance (p_ct , FunctionLike ) and not p_ct .is_type_obj ():
907+ item = expand_and_bind_callable (p_ct , var , itype , name , mx )
922908 else :
923- result = expanded_signature
909+ item = expand_without_binding (ct , var , itype , original_itype , mx )
910+ bound_items .append (item )
911+ result = UnionType .make_union (bound_items )
924912 else :
925913 if not var .is_ready and not mx .no_deferral :
926914 mx .not_ready_callback (var .name , mx .context )
@@ -939,6 +927,37 @@ def analyze_var(
939927 return result
940928
941929
930+ def expand_without_binding (
931+ typ : Type , var : Var , itype : Instance , original_itype : Instance , mx : MemberContext
932+ ) -> Type :
933+ typ = freshen_all_functions_type_vars (typ )
934+ typ = expand_self_type_if_needed (typ , mx , var , original_itype )
935+ expanded = expand_type_by_instance (typ , itype )
936+ freeze_all_type_vars (expanded )
937+ return expanded
938+
939+
940+ def expand_and_bind_callable (
941+ functype : FunctionLike , var : Var , itype : Instance , name : str , mx : MemberContext
942+ ) -> Type :
943+ functype = freshen_all_functions_type_vars (functype )
944+ typ = get_proper_type (expand_self_type (var , functype , mx .original_type ))
945+ assert isinstance (typ , FunctionLike )
946+ typ = check_self_arg (typ , mx .self_type , var .is_classmethod , mx .context , name , mx .msg )
947+ typ = bind_self (typ , mx .self_type , var .is_classmethod )
948+ expanded = expand_type_by_instance (typ , itype )
949+ freeze_all_type_vars (expanded )
950+ if not var .is_property :
951+ return expanded
952+ # TODO: a decorated property can result in Overloaded here.
953+ assert isinstance (expanded , CallableType )
954+ if var .is_settable_property and mx .is_lvalue and var .setter_type is not None :
955+ # TODO: use check_call() to infer better type, same as for __set__().
956+ return expanded .arg_types [0 ]
957+ else :
958+ return expanded .ret_type
959+
960+
942961def expand_self_type_if_needed (
943962 t : Type , mx : MemberContext , var : Var , itype : Instance , is_class : bool = False
944963) -> Type :
@@ -1018,7 +1037,16 @@ def f(self: S) -> T: ...
10181037 selfarg = get_proper_type (item .arg_types [0 ])
10191038 # This level of erasure matches the one in checker.check_func_def(),
10201039 # better keep these two checks consistent.
1021- if subtypes .is_subtype (dispatched_arg_type , erase_typevars (erase_to_bound (selfarg ))):
1040+ if subtypes .is_subtype (
1041+ dispatched_arg_type ,
1042+ erase_typevars (erase_to_bound (selfarg )),
1043+ # This is to work around the fact that erased ParamSpec and TypeVarTuple
1044+ # callables are not always compatible with non-erased ones both ways.
1045+ always_covariant = any (
1046+ not isinstance (tv , TypeVarType ) for tv in get_all_type_vars (selfarg )
1047+ ),
1048+ ignore_pos_arg_names = True ,
1049+ ):
10221050 new_items .append (item )
10231051 elif isinstance (selfarg , ParamSpecType ):
10241052 # TODO: This is not always right. What's the most reasonable thing to do here?
@@ -1151,6 +1179,7 @@ def analyze_class_attribute_access(
11511179 def_vars = set (node .node .info .defn .type_vars )
11521180 if not node .node .is_classvar and node .node .info .self_type :
11531181 def_vars .add (node .node .info .self_type )
1182+ # TODO: should we include ParamSpec etc. here (i.e. use get_all_type_vars)?
11541183 typ_vars = set (get_type_vars (t ))
11551184 if def_vars & typ_vars :
11561185 # Exception: access on Type[...], including first argument of class methods is OK.
@@ -1392,6 +1421,6 @@ def analyze_decorator_or_funcbase_access(
13921421 """
13931422 if isinstance (defn , Decorator ):
13941423 return analyze_var (name , defn .var , itype , mx )
1395- return bind_self (
1396- function_type ( defn , mx .chk . named_type ( "builtins.function" )), original_type = mx .self_type
1397- )
1424+ typ = function_type ( defn , mx . chk . named_type ( "builtins.function" ))
1425+ typ = check_self_arg ( typ , mx . self_type , defn . is_class , mx .context , name , mx .msg )
1426+ return bind_self ( typ , original_type = mx . self_type , is_classmethod = defn . is_class )
0 commit comments