@@ -449,7 +449,6 @@ def reset(self) -> None:
449
449
self .binder = ConditionalTypeBinder (self .options )
450
450
self ._type_maps [1 :] = []
451
451
self ._type_maps [0 ].clear ()
452
- self .temp_type_map = None
453
452
self .expr_checker .reset ()
454
453
self .deferred_nodes = []
455
454
self .partial_types = []
@@ -1374,49 +1373,19 @@ def check_func_def(
1374
1373
)
1375
1374
1376
1375
# 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 )
1377
1379
for i in range (len (typ .arg_types )):
1378
1380
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 ):
1414
1382
# Refuse covariant parameter type variables
1415
1383
# TODO: check recursively for inner type variables
1416
1384
if (
1417
1385
arg_type .variance == COVARIANT
1418
1386
and defn .name not in ("__init__" , "__new__" , "__post_init__" )
1419
1387
and not is_private (defn .name ) # private methods are not inherited
1388
+ and (i != 0 or not found_self )
1420
1389
):
1421
1390
ctx : Context = arg_type
1422
1391
if ctx .line < 0 :
@@ -1566,6 +1535,69 @@ def check_func_def(
1566
1535
1567
1536
self .binder = old_binder
1568
1537
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
+
1569
1601
def is_var_redefined_in_outer_context (self , v : Var , after_line : int ) -> bool :
1570
1602
"""Can the variable be assigned to at module top level or outer function?
1571
1603
@@ -3024,6 +3056,8 @@ def visit_block(self, b: Block) -> None:
3024
3056
break
3025
3057
else :
3026
3058
self .accept (s )
3059
+ # Clear expression cache after each statement to avoid unlimited growth.
3060
+ self .expr_checker .expr_cache .clear ()
3027
3061
3028
3062
def should_report_unreachable_issues (self ) -> bool :
3029
3063
return (
@@ -4005,7 +4039,7 @@ def check_multi_assignment_from_union(
4005
4039
for t , lv in zip (transposed , self .flatten_lvalues (lvalues )):
4006
4040
# We can access _type_maps directly since temporary type maps are
4007
4041
# 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 )))
4009
4043
union_types = tuple (make_simplified_union (col ) for col in transposed )
4010
4044
for expr , items in assignments .items ():
4011
4045
# Bind a union of types collected in 'assignments' to every expression.
@@ -4664,6 +4698,8 @@ def replace_partial_type(
4664
4698
) -> None :
4665
4699
"""Replace the partial type of var with a non-partial type."""
4666
4700
var .type = new_type
4701
+ # Updating a partial type should invalidate expression caches.
4702
+ self .binder .version += 1
4667
4703
del partial_types [var ]
4668
4704
if self .options .allow_redefinition_new :
4669
4705
# When using --allow-redefinition-new, binder tracks all types of
@@ -5303,6 +5339,7 @@ def visit_decorator_inner(
5303
5339
)
5304
5340
if non_trivial_decorator :
5305
5341
self .check_untyped_after_decorator (sig , e .func )
5342
+ self .require_correct_self_argument (sig , e .func )
5306
5343
sig = set_callable_name (sig , e .func )
5307
5344
e .var .type = sig
5308
5345
e .var .is_ready = True
0 commit comments