55from collections .abc import Sequence
66from typing import Callable , TypeVar , cast
77
8- from mypy import message_registry , state , subtypes
8+ from mypy import message_registry , state
99from mypy .checker_shared import TypeCheckerSharedApi
1010from mypy .erasetype import erase_typevars
1111from mypy .expandtype import (
1414 freshen_all_functions_type_vars ,
1515)
1616from mypy .maptype import map_instance_to_supertype
17+ from mypy .meet import is_overlapping_types
1718from mypy .messages import MessageBuilder
1819from mypy .nodes import (
1920 ARG_POS ,
3940 is_final_node ,
4041)
4142from mypy .plugin import AttributeContext
43+ from mypy .subtypes import is_subtype
4244from mypy .typeops import (
4345 bind_self ,
4446 erase_to_bound ,
@@ -745,10 +747,8 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type:
745747 callable_name = callable_name ,
746748 )
747749
748- mx .chk .check_deprecated (dunder_get , mx .context )
749- mx .chk .warn_deprecated_overload_item (
750- dunder_get , mx .context , target = inferred_dunder_get_type , selftype = descriptor_type
751- )
750+ # Search for possible deprecations:
751+ mx .chk .warn_deprecated (dunder_get , mx .context )
752752
753753 inferred_dunder_get_type = get_proper_type (inferred_dunder_get_type )
754754 if isinstance (inferred_dunder_get_type , AnyType ):
@@ -825,10 +825,7 @@ def analyze_descriptor_assign(descriptor_type: Instance, mx: MemberContext) -> T
825825 )
826826
827827 # Search for possible deprecations:
828- mx .chk .check_deprecated (dunder_set , mx .context )
829- mx .chk .warn_deprecated_overload_item (
830- dunder_set , mx .context , target = inferred_dunder_set_type , selftype = descriptor_type
831- )
828+ mx .chk .warn_deprecated (dunder_set , mx .context )
832829
833830 # In the following cases, a message already will have been recorded in check_call.
834831 if (not isinstance (inferred_dunder_set_type , CallableType )) or (
@@ -1053,6 +1050,7 @@ def f(self: S) -> T: ...
10531050 new_items = []
10541051 if is_classmethod :
10551052 dispatched_arg_type = TypeType .make_normalized (dispatched_arg_type )
1053+ p_dispatched_arg_type = get_proper_type (dispatched_arg_type )
10561054
10571055 for item in items :
10581056 if not item .arg_types or item .arg_kinds [0 ] not in (ARG_POS , ARG_STAR ):
@@ -1061,28 +1059,42 @@ def f(self: S) -> T: ...
10611059 # This is pretty bad, so just return the original signature if
10621060 # there is at least one such error.
10631061 return functype
1064- else :
1065- selfarg = get_proper_type (item .arg_types [0 ])
1066- # This matches similar special-casing in bind_self(), see more details there.
1067- self_callable = name == "__call__" and isinstance (selfarg , CallableType )
1068- if self_callable or subtypes .is_subtype (
1069- dispatched_arg_type ,
1070- # This level of erasure matches the one in checker.check_func_def(),
1071- # better keep these two checks consistent.
1072- erase_typevars (erase_to_bound (selfarg )),
1073- # This is to work around the fact that erased ParamSpec and TypeVarTuple
1074- # callables are not always compatible with non-erased ones both ways.
1075- always_covariant = any (
1076- not isinstance (tv , TypeVarType ) for tv in get_all_type_vars (selfarg )
1077- ),
1078- ignore_pos_arg_names = True ,
1079- ):
1080- new_items .append (item )
1081- elif isinstance (selfarg , ParamSpecType ):
1082- # TODO: This is not always right. What's the most reasonable thing to do here?
1083- new_items .append (item )
1084- elif isinstance (selfarg , TypeVarTupleType ):
1085- raise NotImplementedError
1062+ selfarg = get_proper_type (item .arg_types [0 ])
1063+ if isinstance (selfarg , Instance ) and isinstance (p_dispatched_arg_type , Instance ):
1064+ if selfarg .type is p_dispatched_arg_type .type and selfarg .args :
1065+ if not is_overlapping_types (p_dispatched_arg_type , selfarg ):
1066+ # This special casing is needed since `actual <: erased(template)`
1067+ # logic below doesn't always work, and a more correct approach may
1068+ # be tricky.
1069+ continue
1070+ new_items .append (item )
1071+
1072+ if new_items :
1073+ items = new_items
1074+ new_items = []
1075+
1076+ for item in items :
1077+ selfarg = get_proper_type (item .arg_types [0 ])
1078+ # This matches similar special-casing in bind_self(), see more details there.
1079+ self_callable = name == "__call__" and isinstance (selfarg , CallableType )
1080+ if self_callable or is_subtype (
1081+ dispatched_arg_type ,
1082+ # This level of erasure matches the one in checker.check_func_def(),
1083+ # better keep these two checks consistent.
1084+ erase_typevars (erase_to_bound (selfarg )),
1085+ # This is to work around the fact that erased ParamSpec and TypeVarTuple
1086+ # callables are not always compatible with non-erased ones both ways.
1087+ always_covariant = any (
1088+ not isinstance (tv , TypeVarType ) for tv in get_all_type_vars (selfarg )
1089+ ),
1090+ ignore_pos_arg_names = True ,
1091+ ):
1092+ new_items .append (item )
1093+ elif isinstance (selfarg , ParamSpecType ):
1094+ # TODO: This is not always right. What's the most reasonable thing to do here?
1095+ new_items .append (item )
1096+ elif isinstance (selfarg , TypeVarTupleType ):
1097+ raise NotImplementedError
10861098 if not new_items :
10871099 # Choose first item for the message (it may be not very helpful for overloads).
10881100 msg .incompatible_self_argument (
0 commit comments