@@ -2134,40 +2134,17 @@ def check_method_or_accessor_override_for_base(
2134
2134
return None
2135
2135
return found_base_method
2136
2136
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 :
2140
2138
"""Check override of a setter type of a mutable attribute.
2141
2139
2142
2140
Currently, this should be only called when either base node or the current node
2143
2141
is a custom settable property (i.e. where setter type is different from getter type).
2144
2142
Note that this check is contravariant.
2145
2143
"""
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
2171
2148
2172
2149
if not is_subtype (original_type , typ ):
2173
2150
self .msg .incompatible_setter_override (defn .items [1 ], typ , original_type , base )
@@ -2192,28 +2169,19 @@ def check_method_override_for_base_with_name(
2192
2169
context = defn .func
2193
2170
2194
2171
# Construct the type of the overriding method.
2195
- # TODO: this logic is much less complete than similar one in checkmember.py
2196
2172
if isinstance (defn , (FuncDef , OverloadedFuncDef )):
2197
- typ : Type = self .function_type (defn )
2198
2173
override_class_or_static = defn .is_class or defn .is_static
2199
- override_class = defn .is_class
2200
2174
else :
2201
- assert defn .var .is_ready
2202
- assert defn .var .type is not None
2203
- typ = defn .var .type
2204
2175
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
+ assert typ is not None
2178
+
2212
2179
original_node = base_attr .node
2213
2180
# `original_type` can be partial if (e.g.) it is originally an
2214
2181
# instance variable from an `__init__` block that becomes deferred.
2215
2182
supertype_ready = True
2216
- if original_type is None or isinstance (original_type , PartialType ):
2183
+ original_type , _ = self .node_type_from_base (defn , base , name_override = name )
2184
+ if original_type is None :
2217
2185
supertype_ready = False
2218
2186
if self .pass_num < self .last_pass :
2219
2187
# If there are passes left, defer this node until next pass,
@@ -2255,7 +2223,7 @@ def check_method_override_for_base_with_name(
2255
2223
# supertype is not known precisely.
2256
2224
if supertype_ready :
2257
2225
always_allow_covariant = True
2258
- self .check_setter_type_override (defn , base_attr , base )
2226
+ self .check_setter_type_override (defn , base )
2259
2227
2260
2228
if isinstance (original_node , (FuncDef , OverloadedFuncDef )):
2261
2229
original_class_or_static = original_node .is_class or original_node .is_static
@@ -2265,41 +2233,24 @@ def check_method_override_for_base_with_name(
2265
2233
else :
2266
2234
original_class_or_static = False # a variable can't be class or static
2267
2235
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 )
2236
+ typ = get_proper_type (typ )
2237
+ original_type = get_proper_type (original_type )
2279
2238
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
- )
2239
+ if (
2240
+ is_property (defn )
2241
+ and isinstance (original_node , Var )
2242
+ and not original_node .is_final
2243
+ and (not original_node .is_property or original_node .is_settable_property )
2244
+ and isinstance (defn , Decorator )
2245
+ ):
2246
+ # We only give an error where no other similar errors will be given.
2247
+ if not isinstance (original_type , AnyType ):
2248
+ self .msg .fail (
2249
+ "Cannot override writeable attribute with read-only property" ,
2250
+ # Give an error on function line to match old behaviour.
2251
+ defn .func ,
2252
+ code = codes .OVERRIDE ,
2253
+ )
2303
2254
2304
2255
if isinstance (original_type , AnyType ) or isinstance (typ , AnyType ):
2305
2256
pass
@@ -3412,7 +3363,7 @@ def get_variable_type_context(self, inferred: Var, rvalue: Expression) -> Type |
3412
3363
# For inference within class body, get supertype attribute as it would look on
3413
3364
# a class object for lambdas overriding methods, etc.
3414
3365
base_node = base .names [inferred .name ].node
3415
- base_type , _ = self .lvalue_type_from_base (
3366
+ base_type , _ = self .node_type_from_base (
3416
3367
inferred ,
3417
3368
base ,
3418
3369
is_class = is_method (base_node )
@@ -3523,7 +3474,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
3523
3474
rvalue_type = self .expr_checker .accept (rvalue , lvalue_node .type )
3524
3475
actual_lvalue_type = lvalue_node .type
3525
3476
lvalue_node .type = rvalue_type
3526
- lvalue_type , _ = self .lvalue_type_from_base (lvalue_node , lvalue_node .info )
3477
+ lvalue_type , _ = self .node_type_from_base (lvalue_node , lvalue_node .info )
3527
3478
if lvalue_node .is_inferred and not lvalue_node .explicit_self_type :
3528
3479
lvalue_node .type = actual_lvalue_type
3529
3480
@@ -3542,7 +3493,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
3542
3493
if is_private (lvalue_node .name ):
3543
3494
continue
3544
3495
3545
- base_type , base_node = self .lvalue_type_from_base (lvalue_node , base )
3496
+ base_type , base_node = self .node_type_from_base (lvalue_node , base )
3546
3497
custom_setter = is_custom_settable_property (base_node )
3547
3498
if isinstance (base_type , PartialType ):
3548
3499
base_type = None
@@ -3561,7 +3512,7 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, rvalue: Expression) ->
3561
3512
# base classes are also incompatible
3562
3513
return
3563
3514
if lvalue_type and custom_setter :
3564
- base_type , _ = self .lvalue_type_from_base (
3515
+ base_type , _ = self .node_type_from_base (
3565
3516
lvalue_node , base , setter_type = True
3566
3517
)
3567
3518
# Setter type for a custom property must be ready if
@@ -3612,26 +3563,33 @@ def check_compatibility_super(
3612
3563
)
3613
3564
return ok
3614
3565
3615
- def lvalue_type_from_base (
3616
- self , expr_node : Var , base : TypeInfo , setter_type : bool = False , is_class : bool = False
3566
+ def node_type_from_base (
3567
+ self ,
3568
+ node : SymbolNode ,
3569
+ base : TypeInfo ,
3570
+ * ,
3571
+ setter_type : bool = False ,
3572
+ is_class : bool = False ,
3573
+ name_override : str | None = None ,
3617
3574
) -> tuple [Type | None , SymbolNode | None ]:
3618
- """Find a type for a variable name in base class.
3575
+ """Find a type for a name in base class.
3619
3576
3620
3577
Return the type found and the corresponding node defining the name or None
3621
3578
for both if the name is not defined in base or the node type is not known (yet).
3622
3579
The type returned is already properly mapped/bound to the subclass.
3623
3580
If setter_type is True, return setter types for settable properties (otherwise the
3624
3581
getter type is returned).
3625
3582
"""
3626
- expr_name = expr_node .name
3627
- base_var = base .names .get (expr_name )
3583
+ name = name_override or node .name
3584
+ base_node = base .names .get (name )
3628
3585
3629
3586
# TODO: defer current node if the superclass node is not ready.
3630
3587
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
3588
+ not base_node
3589
+ or isinstance (base_node .node , Var )
3590
+ and not base_node .type
3591
+ or isinstance (base_node .type , PartialType )
3592
+ and base_node .type .type is not None
3635
3593
):
3636
3594
return None , None
3637
3595
@@ -3645,9 +3603,9 @@ def lvalue_type_from_base(
3645
3603
mx = MemberContext (
3646
3604
is_lvalue = setter_type ,
3647
3605
is_super = False ,
3648
- is_operator = mypy .checkexpr .is_operator_method (expr_name ),
3606
+ is_operator = mypy .checkexpr .is_operator_method (name ),
3649
3607
original_type = self_type ,
3650
- context = expr_node ,
3608
+ context = node ,
3651
3609
chk = self ,
3652
3610
suppress_errors = True ,
3653
3611
)
@@ -3656,11 +3614,11 @@ def lvalue_type_from_base(
3656
3614
if is_class :
3657
3615
fallback = instance .type .metaclass_type or mx .named_type ("builtins.type" )
3658
3616
base_type = analyze_class_attribute_access (
3659
- instance , expr_name , mx , mcs_fallback = fallback , override_info = base
3617
+ instance , name , mx , mcs_fallback = fallback , override_info = base
3660
3618
)
3661
3619
else :
3662
- base_type = analyze_instance_member_access (expr_name , instance , mx , base )
3663
- return base_type , base_var .node
3620
+ base_type = analyze_instance_member_access (name , instance , mx , base )
3621
+ return base_type , base_node .node
3664
3622
3665
3623
def check_compatibility_classvar_super (
3666
3624
self , node : Var , base : TypeInfo , base_node : Node | None
@@ -8965,29 +8923,6 @@ def is_custom_settable_property(defn: SymbolNode | None) -> bool:
8965
8923
return not is_same_type (get_property_type (get_proper_type (var .type )), setter_type )
8966
8924
8967
8925
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
-
8991
8926
def get_property_type (t : ProperType ) -> ProperType :
8992
8927
if isinstance (t , CallableType ):
8993
8928
return get_proper_type (t .ret_type )
0 commit comments