|
42 | 42 | erase_to_bound, |
43 | 43 | freeze_all_type_vars, |
44 | 44 | function_type, |
| 45 | + get_all_type_vars, |
45 | 46 | get_type_vars, |
46 | 47 | make_simplified_union, |
47 | 48 | supported_self_type, |
@@ -604,7 +605,10 @@ def analyze_member_var_access( |
604 | 605 | setattr_meth = info.get_method("__setattr__") |
605 | 606 | if setattr_meth and setattr_meth.info.fullname != "builtins.object": |
606 | 607 | bound_type = analyze_decorator_or_funcbase_access( |
607 | | - defn=setattr_meth, itype=itype, name=name, mx=mx.copy_modified(is_lvalue=False) |
| 608 | + defn=setattr_meth, |
| 609 | + itype=itype, |
| 610 | + name="__setattr__", |
| 611 | + mx=mx.copy_modified(is_lvalue=False), |
608 | 612 | ) |
609 | 613 | typ = map_instance_to_supertype(itype, setattr_meth.info) |
610 | 614 | setattr_type = get_proper_type(expand_type_by_instance(bound_type, typ)) |
@@ -1031,7 +1035,16 @@ def f(self: S) -> T: ... |
1031 | 1035 | selfarg = get_proper_type(item.arg_types[0]) |
1032 | 1036 | # This level of erasure matches the one in checker.check_func_def(), |
1033 | 1037 | # better keep these two checks consistent. |
1034 | | - if subtypes.is_subtype(dispatched_arg_type, erase_typevars(erase_to_bound(selfarg))): |
| 1038 | + if subtypes.is_subtype( |
| 1039 | + dispatched_arg_type, |
| 1040 | + erase_typevars(erase_to_bound(selfarg)), |
| 1041 | + # This is to work around the fact that erased ParamSpec and TypeVarTuple |
| 1042 | + # callables are not always compatible with non-erased ones both ways. |
| 1043 | + always_covariant=any( |
| 1044 | + not isinstance(tv, TypeVarType) for tv in get_all_type_vars(selfarg) |
| 1045 | + ), |
| 1046 | + ignore_pos_arg_names=True, |
| 1047 | + ): |
1035 | 1048 | new_items.append(item) |
1036 | 1049 | elif isinstance(selfarg, ParamSpecType): |
1037 | 1050 | # TODO: This is not always right. What's the most reasonable thing to do here? |
@@ -1164,6 +1177,7 @@ def analyze_class_attribute_access( |
1164 | 1177 | def_vars = set(node.node.info.defn.type_vars) |
1165 | 1178 | if not node.node.is_classvar and node.node.info.self_type: |
1166 | 1179 | def_vars.add(node.node.info.self_type) |
| 1180 | + # TODO: should we include ParamSpec etc. here (i.e. use get_all_type_vars)? |
1167 | 1181 | typ_vars = set(get_type_vars(t)) |
1168 | 1182 | if def_vars & typ_vars: |
1169 | 1183 | # Exception: access on Type[...], including first argument of class methods is OK. |
@@ -1405,6 +1419,6 @@ def analyze_decorator_or_funcbase_access( |
1405 | 1419 | """ |
1406 | 1420 | if isinstance(defn, Decorator): |
1407 | 1421 | return analyze_var(name, defn.var, itype, mx) |
1408 | | - return bind_self( |
1409 | | - function_type(defn, mx.chk.named_type("builtins.function")), original_type=mx.self_type |
1410 | | - ) |
| 1422 | + typ = function_type(defn, mx.chk.named_type("builtins.function")) |
| 1423 | + typ = check_self_arg(typ, mx.self_type, defn.is_class, mx.context, name, mx.msg) |
| 1424 | + return bind_self(typ, original_type=mx.self_type, is_classmethod=defn.is_class) |
0 commit comments