5
5
from collections .abc import Sequence
6
6
from typing import TYPE_CHECKING , Callable , cast
7
7
8
- from mypy import meet , message_registry , subtypes
8
+ from mypy import message_registry , subtypes
9
9
from mypy .erasetype import erase_typevars
10
10
from mypy .expandtype import (
11
11
expand_self_type ,
@@ -267,7 +267,9 @@ def may_be_awaitable_attribute(
267
267
aw_type = mx .chk .get_precise_awaitable_type (typ , local_errors )
268
268
if aw_type is None :
269
269
return False
270
- _ = _analyze_member_access (name , aw_type , mx , override_info )
270
+ _ = _analyze_member_access (
271
+ name , aw_type , mx .copy_modified (self_type = aw_type ), override_info
272
+ )
271
273
return not local_errors .has_new_errors ()
272
274
273
275
@@ -323,7 +325,7 @@ def analyze_instance_member_access(
323
325
assert isinstance (getter , Decorator )
324
326
if mx .is_lvalue and (len (items := method .items ) > 1 ):
325
327
mx .chk .warn_deprecated (items [1 ], mx .context )
326
- return analyze_var (name , getter .var , typ , info , mx )
328
+ return analyze_var (name , getter .var , typ , mx )
327
329
328
330
if mx .is_lvalue :
329
331
mx .msg .cant_assign_to_method (mx .context )
@@ -340,11 +342,8 @@ def analyze_instance_member_access(
340
342
signature = method .type
341
343
signature = freshen_all_functions_type_vars (signature )
342
344
if not method .is_static :
343
- # TODO: use proper treatment of special methods on unions instead
344
- # of this hack here and below (i.e. mx.self_type).
345
- dispatched_type = meet .meet_types (mx .original_type , typ )
346
345
signature = check_self_arg (
347
- signature , dispatched_type , method .is_class , mx .context , name , mx .msg
346
+ signature , mx . self_type , method .is_class , mx .context , name , mx .msg
348
347
)
349
348
signature = bind_self (signature , mx .self_type , is_classmethod = method .is_class )
350
349
# TODO: should we skip these steps for static methods as well?
@@ -536,7 +535,7 @@ def analyze_member_var_access(
536
535
if mx .is_lvalue and not mx .chk .get_final_context ():
537
536
check_final_member (name , info , mx .msg , mx .context )
538
537
539
- return analyze_var (name , v , itype , info , mx , implicit = implicit )
538
+ return analyze_var (name , v , itype , mx , implicit = implicit )
540
539
elif isinstance (v , FuncDef ):
541
540
assert False , "Did not expect a function"
542
541
elif isinstance (v , MypyFile ):
@@ -560,12 +559,7 @@ def analyze_member_var_access(
560
559
# that the attribute exists
561
560
if method and method .info .fullname != "builtins.object" :
562
561
bound_method = analyze_decorator_or_funcbase_access (
563
- defn = method ,
564
- itype = itype ,
565
- info = info ,
566
- self_type = mx .self_type ,
567
- name = method_name ,
568
- mx = mx ,
562
+ defn = method , itype = itype , name = method_name , mx = mx
569
563
)
570
564
typ = map_instance_to_supertype (itype , method .info )
571
565
getattr_type = get_proper_type (expand_type_by_instance (bound_method , typ ))
@@ -592,12 +586,7 @@ def analyze_member_var_access(
592
586
setattr_meth = info .get_method ("__setattr__" )
593
587
if setattr_meth and setattr_meth .info .fullname != "builtins.object" :
594
588
bound_type = analyze_decorator_or_funcbase_access (
595
- defn = setattr_meth ,
596
- itype = itype ,
597
- info = info ,
598
- self_type = mx .self_type ,
599
- name = name ,
600
- mx = mx .copy_modified (is_lvalue = False ),
589
+ defn = setattr_meth , itype = itype , name = name , mx = mx .copy_modified (is_lvalue = False )
601
590
)
602
591
typ = map_instance_to_supertype (itype , setattr_meth .info )
603
592
setattr_type = get_proper_type (expand_type_by_instance (bound_type , typ ))
@@ -683,10 +672,8 @@ def analyze_descriptor_access(
683
672
bound_method = analyze_decorator_or_funcbase_access (
684
673
defn = dunder_get ,
685
674
itype = descriptor_type ,
686
- info = descriptor_type .type ,
687
- self_type = descriptor_type ,
688
675
name = "__get__" ,
689
- mx = mx ,
676
+ mx = mx . copy_modified ( self_type = descriptor_type ) ,
690
677
)
691
678
692
679
typ = map_instance_to_supertype (descriptor_type , dunder_get .info )
@@ -762,13 +749,7 @@ def is_instance_var(var: Var) -> bool:
762
749
763
750
764
751
def analyze_var (
765
- name : str ,
766
- var : Var ,
767
- itype : Instance ,
768
- info : TypeInfo ,
769
- mx : MemberContext ,
770
- * ,
771
- implicit : bool = False ,
752
+ name : str , var : Var , itype : Instance , mx : MemberContext , * , implicit : bool = False
772
753
) -> Type :
773
754
"""Analyze access to an attribute via a Var node.
774
755
@@ -807,7 +788,9 @@ def analyze_var(
807
788
if isinstance (typ , FunctionLike ) and not typ .is_type_obj ():
808
789
call_type = typ
809
790
elif var .is_property :
810
- call_type = get_proper_type (_analyze_member_access ("__call__" , typ , mx ))
791
+ call_type = get_proper_type (
792
+ _analyze_member_access ("__call__" , typ , mx .copy_modified (self_type = typ ))
793
+ )
811
794
else :
812
795
call_type = typ
813
796
@@ -823,20 +806,12 @@ def analyze_var(
823
806
# Class-level function objects and classmethods become bound methods:
824
807
# the former to the instance, the latter to the class.
825
808
functype : FunctionLike = call_type
826
- # Use meet to narrow original_type to the dispatched type.
827
- # For example, assume
828
- # * A.f: Callable[[A1], None] where A1 <: A (maybe A1 == A)
829
- # * B.f: Callable[[B1], None] where B1 <: B (maybe B1 == B)
830
- # * x: Union[A1, B1]
831
- # In `x.f`, when checking `x` against A1 we assume x is compatible with A
832
- # and similarly for B1 when checking against B
833
- dispatched_type = meet .meet_types (mx .original_type , itype )
834
809
signature = freshen_all_functions_type_vars (functype )
835
810
bound = get_proper_type (expand_self_type (var , signature , mx .original_type ))
836
811
assert isinstance (bound , FunctionLike )
837
812
signature = bound
838
813
signature = check_self_arg (
839
- signature , dispatched_type , var .is_classmethod , mx .context , name , mx .msg
814
+ signature , mx . self_type , var .is_classmethod , mx .context , name , mx .msg
840
815
)
841
816
signature = bind_self (signature , mx .self_type , var .is_classmethod )
842
817
expanded_signature = expand_type_by_instance (signature , itype )
@@ -946,13 +921,9 @@ def check_self_arg(
946
921
For example if the method is defined as:
947
922
class A:
948
923
def f(self: S) -> T: ...
949
- then for 'x.f' we check that meet( type(x), A) <: S. If the method is overloaded, we
950
- select only overloads items that satisfy this requirement. If there are no matching
924
+ then for 'x.f' we check that type(x) <: S. If the method is overloaded, we select
925
+ only overloads items that satisfy this requirement. If there are no matching
951
926
overloads, an error is generated.
952
-
953
- Note: dispatched_arg_type uses a meet to select a relevant item in case if the
954
- original type of 'x' is a union. This is done because several special methods
955
- treat union types in ad-hoc manner, so we can't use MemberContext.self_type yet.
956
927
"""
957
928
items = functype .items
958
929
if not items :
@@ -1436,22 +1407,17 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P
1436
1407
1437
1408
1438
1409
def analyze_decorator_or_funcbase_access (
1439
- defn : Decorator | FuncBase ,
1440
- itype : Instance ,
1441
- info : TypeInfo ,
1442
- self_type : Type | None ,
1443
- name : str ,
1444
- mx : MemberContext ,
1410
+ defn : Decorator | FuncBase , itype : Instance , name : str , mx : MemberContext
1445
1411
) -> Type :
1446
1412
"""Analyzes the type behind method access.
1447
1413
1448
1414
The function itself can possibly be decorated.
1449
1415
See: https://github.com/python/mypy/issues/10409
1450
1416
"""
1451
1417
if isinstance (defn , Decorator ):
1452
- return analyze_var (name , defn .var , itype , info , mx )
1418
+ return analyze_var (name , defn .var , itype , mx )
1453
1419
return bind_self (
1454
- function_type (defn , mx .chk .named_type ("builtins.function" )), original_type = self_type
1420
+ function_type (defn , mx .chk .named_type ("builtins.function" )), original_type = mx . self_type
1455
1421
)
1456
1422
1457
1423
0 commit comments