@@ -449,7 +449,6 @@ def reset(self) -> None:
449449 self .binder = ConditionalTypeBinder (self .options )
450450 self ._type_maps [1 :] = []
451451 self ._type_maps [0 ].clear ()
452- self .temp_type_map = None
453452 self .expr_checker .reset ()
454453 self .deferred_nodes = []
455454 self .partial_types = []
@@ -1374,49 +1373,19 @@ def check_func_def(
13741373 )
13751374
13761375 # Store argument types.
1376+ found_self = False
1377+ if isinstance (defn , FuncDef ) and not defn .is_decorated :
1378+ found_self = self .require_correct_self_argument (typ , defn )
13771379 for i in range (len (typ .arg_types )):
13781380 arg_type = typ .arg_types [i ]
1379- if (
1380- isinstance (defn , FuncDef )
1381- and ref_type is not None
1382- and i == 0
1383- and defn .has_self_or_cls_argument
1384- and typ .arg_kinds [0 ] not in [nodes .ARG_STAR , nodes .ARG_STAR2 ]
1385- ):
1386- if defn .is_class or defn .name == "__new__" :
1387- ref_type = mypy .types .TypeType .make_normalized (ref_type )
1388- if not is_same_type (arg_type , ref_type ):
1389- # This level of erasure matches the one in checkmember.check_self_arg(),
1390- # better keep these two checks consistent.
1391- erased = get_proper_type (erase_typevars (erase_to_bound (arg_type )))
1392- if not is_subtype (ref_type , erased , ignore_type_params = True ):
1393- if (
1394- isinstance (erased , Instance )
1395- and erased .type .is_protocol
1396- or isinstance (erased , TypeType )
1397- and isinstance (erased .item , Instance )
1398- and erased .item .type .is_protocol
1399- ):
1400- # We allow the explicit self-type to be not a supertype of
1401- # the current class if it is a protocol. For such cases
1402- # the consistency check will be performed at call sites.
1403- msg = None
1404- elif typ .arg_names [i ] in {"self" , "cls" }:
1405- msg = message_registry .ERASED_SELF_TYPE_NOT_SUPERTYPE .format (
1406- erased .str_with_options (self .options ),
1407- ref_type .str_with_options (self .options ),
1408- )
1409- else :
1410- msg = message_registry .MISSING_OR_INVALID_SELF_TYPE
1411- if msg :
1412- self .fail (msg , defn )
1413- elif isinstance (arg_type , TypeVarType ):
1381+ if isinstance (arg_type , TypeVarType ):
14141382 # Refuse covariant parameter type variables
14151383 # TODO: check recursively for inner type variables
14161384 if (
14171385 arg_type .variance == COVARIANT
14181386 and defn .name not in ("__init__" , "__new__" , "__post_init__" )
14191387 and not is_private (defn .name ) # private methods are not inherited
1388+ and (i != 0 or not found_self )
14201389 ):
14211390 ctx : Context = arg_type
14221391 if ctx .line < 0 :
@@ -1566,6 +1535,69 @@ def check_func_def(
15661535
15671536 self .binder = old_binder
15681537
1538+ def require_correct_self_argument (self , func : Type , defn : FuncDef ) -> bool :
1539+ func = get_proper_type (func )
1540+ if not isinstance (func , CallableType ):
1541+ return False
1542+
1543+ # Do not report errors for untyped methods in classes nested in untyped funcs.
1544+ if not (
1545+ self .options .check_untyped_defs
1546+ or len (self .dynamic_funcs ) < 2
1547+ or not self .dynamic_funcs [- 2 ]
1548+ or not defn .is_dynamic ()
1549+ ):
1550+ return bool (func .arg_types )
1551+
1552+ with self .scope .push_function (defn ):
1553+ # We temporary push the definition to get the self type as
1554+ # visible from *inside* of this function/method.
1555+ ref_type : Type | None = self .scope .active_self_type ()
1556+ if ref_type is None :
1557+ return False
1558+
1559+ if not defn .has_self_or_cls_argument or (
1560+ func .arg_kinds and func .arg_kinds [0 ] in [nodes .ARG_STAR , nodes .ARG_STAR2 ]
1561+ ):
1562+ return False
1563+
1564+ if not func .arg_types :
1565+ self .fail (
1566+ 'Method must have at least one argument. Did you forget the "self" argument?' , defn
1567+ )
1568+ return False
1569+
1570+ arg_type = func .arg_types [0 ]
1571+ if defn .is_class or defn .name == "__new__" :
1572+ ref_type = mypy .types .TypeType .make_normalized (ref_type )
1573+ if is_same_type (arg_type , ref_type ):
1574+ return True
1575+
1576+ # This level of erasure matches the one in checkmember.check_self_arg(),
1577+ # better keep these two checks consistent.
1578+ erased = get_proper_type (erase_typevars (erase_to_bound (arg_type )))
1579+ if not is_subtype (ref_type , erased , ignore_type_params = True ):
1580+ if (
1581+ isinstance (erased , Instance )
1582+ and erased .type .is_protocol
1583+ or isinstance (erased , TypeType )
1584+ and isinstance (erased .item , Instance )
1585+ and erased .item .type .is_protocol
1586+ ):
1587+ # We allow the explicit self-type to be not a supertype of
1588+ # the current class if it is a protocol. For such cases
1589+ # the consistency check will be performed at call sites.
1590+ msg = None
1591+ elif func .arg_names [0 ] in {"self" , "cls" }:
1592+ msg = message_registry .ERASED_SELF_TYPE_NOT_SUPERTYPE .format (
1593+ erased .str_with_options (self .options ), ref_type .str_with_options (self .options )
1594+ )
1595+ else :
1596+ msg = message_registry .MISSING_OR_INVALID_SELF_TYPE
1597+ if msg :
1598+ self .fail (msg , defn )
1599+ return True
1600+
15691601 def is_var_redefined_in_outer_context (self , v : Var , after_line : int ) -> bool :
15701602 """Can the variable be assigned to at module top level or outer function?
15711603
@@ -3024,6 +3056,8 @@ def visit_block(self, b: Block) -> None:
30243056 break
30253057 else :
30263058 self .accept (s )
3059+ # Clear expression cache after each statement to avoid unlimited growth.
3060+ self .expr_checker .expr_cache .clear ()
30273061
30283062 def should_report_unreachable_issues (self ) -> bool :
30293063 return (
@@ -4005,7 +4039,7 @@ def check_multi_assignment_from_union(
40054039 for t , lv in zip (transposed , self .flatten_lvalues (lvalues )):
40064040 # We can access _type_maps directly since temporary type maps are
40074041 # only created within expressions.
4008- t .append (self ._type_maps [0 ].pop (lv , AnyType (TypeOfAny .special_form )))
4042+ t .append (self ._type_maps [- 1 ].pop (lv , AnyType (TypeOfAny .special_form )))
40094043 union_types = tuple (make_simplified_union (col ) for col in transposed )
40104044 for expr , items in assignments .items ():
40114045 # Bind a union of types collected in 'assignments' to every expression.
@@ -4664,6 +4698,8 @@ def replace_partial_type(
46644698 ) -> None :
46654699 """Replace the partial type of var with a non-partial type."""
46664700 var .type = new_type
4701+ # Updating a partial type should invalidate expression caches.
4702+ self .binder .version += 1
46674703 del partial_types [var ]
46684704 if self .options .allow_redefinition_new :
46694705 # When using --allow-redefinition-new, binder tracks all types of
@@ -5303,6 +5339,7 @@ def visit_decorator_inner(
53035339 )
53045340 if non_trivial_decorator :
53055341 self .check_untyped_after_decorator (sig , e .func )
5342+ self .require_correct_self_argument (sig , e .func )
53065343 sig = set_callable_name (sig , e .func )
53075344 e .var .type = sig
53085345 e .var .is_ready = True
0 commit comments