@@ -2134,40 +2134,17 @@ def check_method_or_accessor_override_for_base(
21342134 return None
21352135 return found_base_method
21362136
2137- def check_setter_type_override (
2138- self , defn : OverloadedFuncDef , base_attr : SymbolTableNode , base : TypeInfo
2139- ) -> None :
2137+ def check_setter_type_override (self , defn : OverloadedFuncDef , base : TypeInfo ) -> None :
21402138 """Check override of a setter type of a mutable attribute.
21412139
21422140 Currently, this should be only called when either base node or the current node
21432141 is a custom settable property (i.e. where setter type is different from getter type).
21442142 Note that this check is contravariant.
21452143 """
2146- base_node = base_attr .node
2147- assert isinstance (base_node , (OverloadedFuncDef , Var ))
2148- original_type , is_original_setter = get_raw_setter_type (base_node )
2149- if isinstance (base_node , Var ):
2150- expanded_type = map_type_from_supertype (original_type , defn .info , base )
2151- original_type = get_proper_type (
2152- expand_self_type (base_node , expanded_type , fill_typevars (defn .info ))
2153- )
2154- else :
2155- assert isinstance (original_type , ProperType )
2156- assert isinstance (original_type , CallableType )
2157- original_type = self .bind_and_map_method (base_attr , original_type , defn .info , base )
2158- assert isinstance (original_type , CallableType )
2159- if is_original_setter :
2160- original_type = original_type .arg_types [0 ]
2161- else :
2162- original_type = original_type .ret_type
2163-
2164- typ , is_setter = get_raw_setter_type (defn )
2165- assert isinstance (typ , ProperType ) and isinstance (typ , CallableType )
2166- typ = bind_self (typ , self .scope .active_self_type ())
2167- if is_setter :
2168- typ = typ .arg_types [0 ]
2169- else :
2170- typ = typ .ret_type
2144+ typ , _ = self .node_type_from_base (defn , defn .info , setter_type = True )
2145+ original_type , _ = self .node_type_from_base (defn , base , setter_type = True )
2146+ # The caller should handle deferrals.
2147+ assert typ is not None and original_type is not None
21712148
21722149 if not is_subtype (original_type , typ ):
21732150 self .msg .incompatible_setter_override (defn .items [1 ], typ , original_type , base )
@@ -2192,28 +2169,20 @@ def check_method_override_for_base_with_name(
21922169 context = defn .func
21932170
21942171 # Construct the type of the overriding method.
2195- # TODO: this logic is much less complete than similar one in checkmember.py
21962172 if isinstance (defn , (FuncDef , OverloadedFuncDef )):
2197- typ : Type = self .function_type (defn )
21982173 override_class_or_static = defn .is_class or defn .is_static
2199- override_class = defn .is_class
22002174 else :
2201- assert defn .var .is_ready
2202- assert defn .var .type is not None
2203- typ = defn .var .type
22042175 override_class_or_static = defn .func .is_class or defn .func .is_static
2205- override_class = defn .func .is_class
2206- typ = get_proper_type (typ )
2207- if isinstance (typ , FunctionLike ) and not is_static (context ):
2208- typ = bind_self (typ , self .scope .active_self_type (), is_classmethod = override_class )
2209- # Map the overridden method type to subtype context so that
2210- # it can be checked for compatibility.
2211- original_type = get_proper_type (base_attr .type )
2176+ typ , _ = self .node_type_from_base (defn , defn .info )
2177+ # TODO: defer if current node is a decorator that is not ready yet.
2178+ assert typ is not None
2179+
22122180 original_node = base_attr .node
22132181 # `original_type` can be partial if (e.g.) it is originally an
22142182 # instance variable from an `__init__` block that becomes deferred.
22152183 supertype_ready = True
2216- if original_type is None or isinstance (original_type , PartialType ):
2184+ original_type , _ = self .node_type_from_base (defn , base , name_override = name )
2185+ if original_type is None :
22172186 supertype_ready = False
22182187 if self .pass_num < self .last_pass :
22192188 # If there are passes left, defer this node until next pass,
@@ -2255,7 +2224,7 @@ def check_method_override_for_base_with_name(
22552224 # supertype is not known precisely.
22562225 if supertype_ready :
22572226 always_allow_covariant = True
2258- self .check_setter_type_override (defn , base_attr , base )
2227+ self .check_setter_type_override (defn , base )
22592228
22602229 if isinstance (original_node , (FuncDef , OverloadedFuncDef )):
22612230 original_class_or_static = original_node .is_class or original_node .is_static
@@ -2265,41 +2234,24 @@ def check_method_override_for_base_with_name(
22652234 else :
22662235 original_class_or_static = False # a variable can't be class or static
22672236
2268- if isinstance (original_type , FunctionLike ):
2269- original_type = self .bind_and_map_method (base_attr , original_type , defn .info , base )
2270- if original_node and is_property (original_node ):
2271- original_type = get_property_type (original_type )
2272-
2273- if isinstance (original_node , Var ):
2274- expanded_type = map_type_from_supertype (original_type , defn .info , base )
2275- expanded_type = expand_self_type (
2276- original_node , expanded_type , fill_typevars (defn .info )
2277- )
2278- original_type = get_proper_type (expanded_type )
2237+ typ = get_proper_type (typ )
2238+ original_type = get_proper_type (original_type )
22792239
2280- if is_property (defn ):
2281- inner : FunctionLike | None
2282- if isinstance (typ , FunctionLike ):
2283- inner = typ
2284- else :
2285- inner = self .extract_callable_type (typ , context )
2286- if inner is not None :
2287- typ = inner
2288- typ = get_property_type (typ )
2289- if (
2290- isinstance (original_node , Var )
2291- and not original_node .is_final
2292- and (not original_node .is_property or original_node .is_settable_property )
2293- and isinstance (defn , Decorator )
2294- ):
2295- # We only give an error where no other similar errors will be given.
2296- if not isinstance (original_type , AnyType ):
2297- self .msg .fail (
2298- "Cannot override writeable attribute with read-only property" ,
2299- # Give an error on function line to match old behaviour.
2300- defn .func ,
2301- code = codes .OVERRIDE ,
2302- )
2240+ if (
2241+ is_property (defn )
2242+ and isinstance (original_node , Var )
2243+ and not original_node .is_final
2244+ and (not original_node .is_property or original_node .is_settable_property )
2245+ and isinstance (defn , Decorator )
2246+ ):
2247+ # We only give an error where no other similar errors will be given.
2248+ if not isinstance (original_type , AnyType ):
2249+ self .msg .fail (
2250+ "Cannot override writeable attribute with read-only property" ,
2251+ # Give an error on function line to match old behaviour.
2252+ defn .func ,
2253+ code = codes .OVERRIDE ,
2254+ )
23032255
23042256 if isinstance (original_type , AnyType ) or isinstance (typ , AnyType ):
23052257 pass
@@ -3412,7 +3364,7 @@ def get_variable_type_context(self, inferred: Var, rvalue: Expression) -> Type |
34123364 # For inference within class body, get supertype attribute as it would look on
34133365 # a class object for lambdas overriding methods, etc.
34143366 base_node = base .names [inferred .name ].node
3415- base_type , _ = self .lvalue_type_from_base (
3367+ base_type , _ = self .node_type_from_base (
34163368 inferred ,
34173369 base ,
34183370 is_class = is_method (base_node )
@@ -3523,7 +3475,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
35233475 rvalue_type = self .expr_checker .accept (rvalue , lvalue_node .type )
35243476 actual_lvalue_type = lvalue_node .type
35253477 lvalue_node .type = rvalue_type
3526- lvalue_type , _ = self .lvalue_type_from_base (lvalue_node , lvalue_node .info )
3478+ lvalue_type , _ = self .node_type_from_base (lvalue_node , lvalue_node .info )
35273479 if lvalue_node .is_inferred and not lvalue_node .explicit_self_type :
35283480 lvalue_node .type = actual_lvalue_type
35293481
@@ -3542,7 +3494,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
35423494 if is_private (lvalue_node .name ):
35433495 continue
35443496
3545- base_type , base_node = self .lvalue_type_from_base (lvalue_node , base )
3497+ base_type , base_node = self .node_type_from_base (lvalue_node , base )
35463498 custom_setter = is_custom_settable_property (base_node )
35473499 if isinstance (base_type , PartialType ):
35483500 base_type = None
@@ -3561,7 +3513,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
35613513 # base classes are also incompatible
35623514 return
35633515 if lvalue_type and custom_setter :
3564- base_type , _ = self .lvalue_type_from_base (
3516+ base_type , _ = self .node_type_from_base (
35653517 lvalue_node , base , setter_type = True
35663518 )
35673519 # Setter type for a custom property must be ready if
@@ -3612,26 +3564,33 @@ def check_compatibility_super(
36123564 )
36133565 return ok
36143566
3615- def lvalue_type_from_base (
3616- self , expr_node : Var , base : TypeInfo , setter_type : bool = False , is_class : bool = False
3567+ def node_type_from_base (
3568+ self ,
3569+ node : SymbolNode ,
3570+ base : TypeInfo ,
3571+ * ,
3572+ setter_type : bool = False ,
3573+ is_class : bool = False ,
3574+ name_override : str | None = None ,
36173575 ) -> tuple [Type | None , SymbolNode | None ]:
3618- """Find a type for a variable name in base class.
3576+ """Find a type for a name in base class.
36193577
36203578 Return the type found and the corresponding node defining the name or None
36213579 for both if the name is not defined in base or the node type is not known (yet).
36223580 The type returned is already properly mapped/bound to the subclass.
36233581 If setter_type is True, return setter types for settable properties (otherwise the
36243582 getter type is returned).
36253583 """
3626- expr_name = expr_node .name
3627- base_var = base .names .get (expr_name )
3584+ name = name_override or node .name
3585+ base_node = base .names .get (name )
36283586
36293587 # TODO: defer current node if the superclass node is not ready.
36303588 if (
3631- not base_var
3632- or not base_var .type
3633- or isinstance (base_var .type , PartialType )
3634- and base_var .type .type is not None
3589+ not base_node
3590+ or isinstance (base_node .node , Var )
3591+ and not base_node .type
3592+ or isinstance (base_node .type , PartialType )
3593+ and base_node .type .type is not None
36353594 ):
36363595 return None , None
36373596
@@ -3645,9 +3604,9 @@ def lvalue_type_from_base(
36453604 mx = MemberContext (
36463605 is_lvalue = setter_type ,
36473606 is_super = False ,
3648- is_operator = mypy .checkexpr .is_operator_method (expr_name ),
3607+ is_operator = mypy .checkexpr .is_operator_method (name ),
36493608 original_type = self_type ,
3650- context = expr_node ,
3609+ context = node ,
36513610 chk = self ,
36523611 suppress_errors = True ,
36533612 )
@@ -3656,11 +3615,11 @@ def lvalue_type_from_base(
36563615 if is_class :
36573616 fallback = instance .type .metaclass_type or mx .named_type ("builtins.type" )
36583617 base_type = analyze_class_attribute_access (
3659- instance , expr_name , mx , mcs_fallback = fallback , override_info = base
3618+ instance , name , mx , mcs_fallback = fallback , override_info = base
36603619 )
36613620 else :
3662- base_type = analyze_instance_member_access (expr_name , instance , mx , base )
3663- return base_type , base_var .node
3621+ base_type = analyze_instance_member_access (name , instance , mx , base )
3622+ return base_type , base_node .node
36643623
36653624 def check_compatibility_classvar_super (
36663625 self , node : Var , base : TypeInfo , base_node : Node | None
@@ -8965,29 +8924,6 @@ def is_custom_settable_property(defn: SymbolNode | None) -> bool:
89658924 return not is_same_type (get_property_type (get_proper_type (var .type )), setter_type )
89668925
89678926
8968- def get_raw_setter_type (defn : OverloadedFuncDef | Var ) -> tuple [Type , bool ]:
8969- """Get an effective original setter type for a node.
8970-
8971- For a variable it is simply its type. For a property it is the type
8972- of the setter method (if not None), or the getter method (used as fallback
8973- for the plugin generated properties).
8974- Return the type and a flag indicating that we didn't fall back to getter.
8975- """
8976- if isinstance (defn , Var ):
8977- # This function should not be called if the var is not ready.
8978- assert defn .type is not None
8979- return defn .type , True
8980- first_item = defn .items [0 ]
8981- assert isinstance (first_item , Decorator )
8982- var = first_item .var
8983- # This function may be called on non-custom properties, so we need
8984- # to handle the situation when it is synthetic (plugin generated).
8985- if var .setter_type is not None :
8986- return var .setter_type , True
8987- assert var .type is not None
8988- return var .type , False
8989-
8990-
89918927def get_property_type (t : ProperType ) -> ProperType :
89928928 if isinstance (t , CallableType ):
89938929 return get_proper_type (t .ret_type )
0 commit comments