|
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