1212import mypy .checkexpr
1313from mypy import errorcodes as codes , join , message_registry , nodes , operators
1414from mypy .binder import ConditionalTypeBinder , Frame , get_declaration
15- from mypy .checkmember import analyze_member_access
15+ from mypy .checkmember import (
16+ MemberContext ,
17+ analyze_descriptor_access ,
18+ analyze_instance_member_access ,
19+ analyze_member_access ,
20+ )
1621from mypy .checkpattern import PatternChecker
1722from mypy .constraints import SUPERTYPE_OF
1823from mypy .erasetype import erase_type , erase_typevars , remove_instance_last_known_values
1924from mypy .errorcodes import TYPE_VAR , UNUSED_AWAITABLE , UNUSED_COROUTINE , ErrorCode
2025from mypy .errors import Errors , ErrorWatcher , report_internal_error
21- from mypy .expandtype import expand_self_type , expand_type , expand_type_by_instance
26+ from mypy .expandtype import expand_self_type , expand_type
2227from mypy .literals import Key , extract_var_from_literal_hash , literal , literal_hash
2328from mypy .maptype import map_instance_to_supertype
2429from mypy .meet import is_overlapping_erased_types , is_overlapping_types , meet_types
@@ -3583,31 +3588,39 @@ def check_compatibility_super(
35833588 base_type = get_proper_type (base_type )
35843589 compare_type = get_proper_type (compare_type )
35853590 if compare_type :
3586- if isinstance (base_type , CallableType ) and isinstance (compare_type , CallableType ):
3587- base_static = is_node_static (base_node )
3591+ # Unlike for base_type, where we use the full analyze_member_access(), we know
3592+ # that subclass node is an assignment, so we use a much simpler logic: just bind
3593+ # self or invoke descriptors. Although this may not cover some niche corner
3594+ # cases, it is faster, and works with current logic where we check overrides
3595+ # before storing inferred variable type.
3596+ if isinstance (compare_type , CallableType ):
35883597 compare_static = is_node_static (compare_node )
3589-
3590- # In case compare_static is unknown, also check
3591- # if 'definition' is set. The most common case for
3592- # this is with TempNode(), where we lose all
3593- # information about the real rvalue node (but only get
3594- # the rvalue type)
3598+ # Since this method may be called before storing inferred type,
3599+ # fall back to rvalue to obtain the static method flag.
35953600 if compare_static is None and compare_type .definition :
35963601 compare_static = is_node_static (compare_type .definition )
3597-
35983602 # Compare against False, as is_node_static can return None
3599- if base_static is False and compare_static is False :
3600- # Class-level function objects and classmethods become bound
3601- # methods: the former to the instance, the latter to the
3602- # class
3603- base_type = bind_self (base_type , self .scope .active_self_type ())
3603+ if compare_static is False :
3604+ # TODO: handle aliases to class methods (similarly).
36043605 compare_type = bind_self (compare_type , self .scope .active_self_type ())
36053606
3606- # If we are a static method, ensure to also tell the
3607- # lvalue it now contains a static method
3608- if base_static and compare_static :
3609- lvalue_node .is_staticmethod = True
3607+ elif isinstance (compare_type , Instance ):
3608+ self_type = self .scope .active_self_type ()
3609+ assert self_type is not None , "Internal error: base lookup outside class"
3610+ mx = MemberContext (
3611+ is_lvalue = False ,
3612+ is_super = False ,
3613+ is_operator = False ,
3614+ original_type = self_type ,
3615+ context = lvalue ,
3616+ chk = self ,
3617+ suppress_errors = True ,
3618+ )
3619+ with self .msg .filter_errors ():
3620+ compare_type = analyze_descriptor_access (compare_type , mx )
36103621
3622+ # TODO: check __set__() type override for custom descriptors.
3623+ # TODO: for descriptors check also class object access override.
36113624 ok = self .check_subtype (
36123625 compare_type ,
36133626 base_type ,
@@ -3647,49 +3660,30 @@ def lvalue_type_from_base(
36473660 expr_name = expr_node .name
36483661 base_var = base .names .get (expr_name )
36493662
3650- if not base_var :
3651- return None , None
3652- base_node = base_var .node
3653- base_type = base_var .type
3654- if isinstance (base_node , Var ) and base_type is not None :
3655- base_type = expand_self_type (base_node , base_type , fill_typevars (expr_node .info ))
3656- if isinstance (base_node , Decorator ):
3657- base_node = base_node .func
3658- base_type = base_node .type
3659-
3660- if not base_type :
3663+ # TODO: defer current node if the superclass node is not ready.
3664+ if not base_var or not base_var .type :
36613665 return None , None
3662- if not has_no_typevars (base_type ):
3663- self_type = self .scope .active_self_type ()
3664- assert self_type is not None , "Internal error: base lookup outside class"
3665- if isinstance (self_type , TupleType ):
3666- instance = tuple_fallback (self_type )
3667- else :
3668- instance = self_type
3669- itype = map_instance_to_supertype (instance , base )
3670- base_type = expand_type_by_instance (base_type , itype )
3671-
3672- base_type = get_proper_type (base_type )
3673- if isinstance (base_type , CallableType ) and isinstance (base_node , FuncDef ):
3674- # If we are a property, return the Type of the return
3675- # value, not the Callable
3676- if base_node .is_property :
3677- base_type = get_proper_type (base_type .ret_type )
3678- if isinstance (base_type , FunctionLike ) and isinstance (base_node , OverloadedFuncDef ):
3679- # Same for properties with setter
3680- if base_node .is_property :
3681- if setter_type :
3682- assert isinstance (base_node .items [0 ], Decorator )
3683- base_type = base_node .items [0 ].var .setter_type
3684- # This flag is True only for custom properties, so it is safe to assert.
3685- assert base_type is not None
3686- base_type = self .bind_and_map_method (base_var , base_type , expr_node .info , base )
3687- assert isinstance (base_type , CallableType )
3688- base_type = get_proper_type (base_type .arg_types [0 ])
3689- else :
3690- base_type = base_type .items [0 ].ret_type
36913666
3692- return base_type , base_node
3667+ self_type = self .scope .active_self_type ()
3668+ assert self_type is not None , "Internal error: base lookup outside class"
3669+ if isinstance (self_type , TupleType ):
3670+ instance = tuple_fallback (self_type )
3671+ else :
3672+ instance = self_type
3673+
3674+ mx = MemberContext (
3675+ is_lvalue = setter_type ,
3676+ is_super = False ,
3677+ is_operator = False ,
3678+ original_type = self_type ,
3679+ context = expr_node ,
3680+ chk = self ,
3681+ suppress_errors = True ,
3682+ )
3683+ # TODO: we should not filter "cannot determine type" errors here.
3684+ with self .msg .filter_errors ():
3685+ base_type = analyze_instance_member_access (expr_name , instance , mx , base )
3686+ return base_type , base_var .node
36933687
36943688 def check_compatibility_classvar_super (
36953689 self , node : Var , base : TypeInfo , base_node : Node | None
@@ -4515,6 +4509,7 @@ def set_inferred_type(self, var: Var, lvalue: Lvalue, type: Type) -> None:
45154509 refers to the variable (lvalue). If var is None, do nothing.
45164510 """
45174511 if var and not self .current_node_deferred :
4512+ # TODO: should we also set 'is_ready = True' here?
45184513 var .type = type
45194514 var .is_inferred = True
45204515 if var not in self .var_decl_frames :
@@ -4525,12 +4520,15 @@ def set_inferred_type(self, var: Var, lvalue: Lvalue, type: Type) -> None:
45254520 if lvalue .def_var is not None :
45264521 self .inferred_attribute_types [lvalue .def_var ] = type
45274522 self .store_type (lvalue , type )
4523+ p_type = get_proper_type (type )
4524+ if isinstance (p_type , CallableType ) and is_node_static (p_type .definition ):
4525+ var .is_staticmethod = True
45284526
45294527 def set_inference_error_fallback_type (self , var : Var , lvalue : Lvalue , type : Type ) -> None :
45304528 """Store best known type for variable if type inference failed.
45314529
45324530 If a program ignores error on type inference error, the variable should get some
4533- inferred type so that if can used later on in the program. Example:
4531+ inferred type so that it can used later on in the program. Example:
45344532
45354533 x = [] # type: ignore
45364534 x.append(1) # Should be ok!
0 commit comments