126126 validate_instance ,
127127)
128128from mypy .typeops import (
129+ bind_self ,
129130 callable_type ,
130131 custom_special_method ,
131132 erase_to_union_or_bound ,
@@ -354,7 +355,9 @@ def visit_name_expr(self, e: NameExpr) -> Type:
354355 """
355356 self .chk .module_refs .update (extract_refexpr_names (e ))
356357 result = self .analyze_ref_expr (e )
357- return self .narrow_type_from_binder (e , result )
358+ narrowed = self .narrow_type_from_binder (e , result )
359+ self .chk .check_deprecated (e .node , e )
360+ return narrowed
358361
359362 def analyze_ref_expr (self , e : RefExpr , lvalue : bool = False ) -> Type :
360363 result : Type | None = None
@@ -1479,6 +1482,10 @@ def check_call_expr_with_callee_type(
14791482 object_type = object_type ,
14801483 )
14811484 proper_callee = get_proper_type (callee_type )
1485+ if isinstance (e .callee , NameExpr ) and isinstance (e .callee .node , OverloadedFuncDef ):
1486+ for item in e .callee .node .items :
1487+ if isinstance (item , Decorator ) and (item .func .type == callee_type ):
1488+ self .chk .check_deprecated (item .func , e )
14821489 if isinstance (e .callee , RefExpr ) and isinstance (proper_callee , CallableType ):
14831490 # Cache it for find_isinstance_check()
14841491 if proper_callee .type_guard is not None :
@@ -3267,7 +3274,9 @@ def visit_member_expr(self, e: MemberExpr, is_lvalue: bool = False) -> Type:
32673274 """Visit member expression (of form e.id)."""
32683275 self .chk .module_refs .update (extract_refexpr_names (e ))
32693276 result = self .analyze_ordinary_member_access (e , is_lvalue )
3270- return self .narrow_type_from_binder (e , result )
3277+ narrowed = self .narrow_type_from_binder (e , result )
3278+ self .chk .warn_deprecated (e .node , e )
3279+ return narrowed
32713280
32723281 def analyze_ordinary_member_access (self , e : MemberExpr , is_lvalue : bool ) -> Type :
32733282 """Analyse member expression or member lvalue."""
@@ -3956,7 +3965,7 @@ def lookup_definer(typ: Instance, attr_name: str) -> str | None:
39563965 # This is the case even if the __add__ method is completely missing and the __radd__
39573966 # method is defined.
39583967
3959- variants_raw = [(left_op , left_type , right_expr )]
3968+ variants_raw = [(op_name , left_op , left_type , right_expr )]
39603969 elif (
39613970 is_subtype (right_type , left_type )
39623971 and isinstance (left_type , Instance )
@@ -3977,19 +3986,25 @@ def lookup_definer(typ: Instance, attr_name: str) -> str | None:
39773986 # As a special case, the alt_promote check makes sure that we don't use the
39783987 # __radd__ method of int if the LHS is a native int type.
39793988
3980- variants_raw = [(right_op , right_type , left_expr ), (left_op , left_type , right_expr )]
3989+ variants_raw = [
3990+ (rev_op_name , right_op , right_type , left_expr ),
3991+ (op_name , left_op , left_type , right_expr ),
3992+ ]
39813993 else :
39823994 # In all other cases, we do the usual thing and call __add__ first and
39833995 # __radd__ second when doing "A() + B()".
39843996
3985- variants_raw = [(left_op , left_type , right_expr ), (right_op , right_type , left_expr )]
3997+ variants_raw = [
3998+ (op_name , left_op , left_type , right_expr ),
3999+ (rev_op_name , right_op , right_type , left_expr ),
4000+ ]
39864001
39874002 # STEP 3:
39884003 # We now filter out all non-existent operators. The 'variants' list contains
39894004 # all operator methods that are actually present, in the order that Python
39904005 # attempts to invoke them.
39914006
3992- variants = [(op , obj , arg ) for (op , obj , arg ) in variants_raw if op is not None ]
4007+ variants = [(na , op , obj , arg ) for (na , op , obj , arg ) in variants_raw if op is not None ]
39934008
39944009 # STEP 4:
39954010 # We now try invoking each one. If an operation succeeds, end early and return
@@ -3998,13 +4013,23 @@ def lookup_definer(typ: Instance, attr_name: str) -> str | None:
39984013
39994014 errors = []
40004015 results = []
4001- for method , obj , arg in variants :
4016+ for name , method , obj , arg in variants :
40024017 with self .msg .filter_errors (save_filtered_errors = True ) as local_errors :
40034018 result = self .check_method_call (op_name , obj , method , [arg ], [ARG_POS ], context )
40044019 if local_errors .has_new_errors ():
40054020 errors .append (local_errors .filtered_errors ())
40064021 results .append (result )
40074022 else :
4023+ if isinstance (obj , Instance ) and isinstance (
4024+ defn := obj .type .get_method (name ), OverloadedFuncDef
4025+ ):
4026+ for item in defn .items :
4027+ if (
4028+ isinstance (item , Decorator )
4029+ and isinstance (typ := item .func .type , CallableType )
4030+ and bind_self (typ ) == result [1 ]
4031+ ):
4032+ self .chk .check_deprecated (item .func , context )
40084033 return result
40094034
40104035 # We finish invoking above operators and no early return happens. Therefore,
0 commit comments