@@ -1369,49 +1369,19 @@ def check_func_def(
13691369 )
13701370
13711371 # Store argument types.
1372+ found_self = False
1373+ if isinstance (defn , FuncDef ) and not defn .is_decorated :
1374+ found_self = self .require_correct_self_argument (typ , defn )
13721375 for i in range (len (typ .arg_types )):
13731376 arg_type = typ .arg_types [i ]
1374- if (
1375- isinstance (defn , FuncDef )
1376- and ref_type is not None
1377- and i == 0
1378- and defn .has_self_or_cls_argument
1379- and typ .arg_kinds [0 ] not in [nodes .ARG_STAR , nodes .ARG_STAR2 ]
1380- ):
1381- if defn .is_class or defn .name == "__new__" :
1382- ref_type = mypy .types .TypeType .make_normalized (ref_type )
1383- if not is_same_type (arg_type , ref_type ):
1384- # This level of erasure matches the one in checkmember.check_self_arg(),
1385- # better keep these two checks consistent.
1386- erased = get_proper_type (erase_typevars (erase_to_bound (arg_type )))
1387- if not is_subtype (ref_type , erased , ignore_type_params = True ):
1388- if (
1389- isinstance (erased , Instance )
1390- and erased .type .is_protocol
1391- or isinstance (erased , TypeType )
1392- and isinstance (erased .item , Instance )
1393- and erased .item .type .is_protocol
1394- ):
1395- # We allow the explicit self-type to be not a supertype of
1396- # the current class if it is a protocol. For such cases
1397- # the consistency check will be performed at call sites.
1398- msg = None
1399- elif typ .arg_names [i ] in {"self" , "cls" }:
1400- msg = message_registry .ERASED_SELF_TYPE_NOT_SUPERTYPE .format (
1401- erased .str_with_options (self .options ),
1402- ref_type .str_with_options (self .options ),
1403- )
1404- else :
1405- msg = message_registry .MISSING_OR_INVALID_SELF_TYPE
1406- if msg :
1407- self .fail (msg , defn )
1408- elif isinstance (arg_type , TypeVarType ):
1377+ if isinstance (arg_type , TypeVarType ):
14091378 # Refuse covariant parameter type variables
14101379 # TODO: check recursively for inner type variables
14111380 if (
14121381 arg_type .variance == COVARIANT
14131382 and defn .name not in ("__init__" , "__new__" , "__post_init__" )
14141383 and not is_private (defn .name ) # private methods are not inherited
1384+ and (i != 0 or not found_self )
14151385 ):
14161386 ctx : Context = arg_type
14171387 if ctx .line < 0 :
@@ -1561,6 +1531,60 @@ def check_func_def(
15611531
15621532 self .binder = old_binder
15631533
1534+ def require_correct_self_argument (self , func : Type , defn : FuncDef ) -> bool :
1535+ func = get_proper_type (func )
1536+ if not isinstance (func , CallableType ):
1537+ return False
1538+
1539+ with self .scope .push_function (defn ):
1540+ # We temporary push the definition to get the self type as
1541+ # visible from *inside* of this function/method.
1542+ ref_type : Type | None = self .scope .active_self_type ()
1543+ if ref_type is None :
1544+ return False
1545+
1546+ if not defn .has_self_or_cls_argument or (
1547+ func .arg_kinds and func .arg_kinds [0 ] in [nodes .ARG_STAR , nodes .ARG_STAR2 ]
1548+ ):
1549+ return False
1550+
1551+ if not func .arg_types :
1552+ self .fail (
1553+ 'Method must have at least one argument. Did you forget the "self" argument?' , defn
1554+ )
1555+ return False
1556+
1557+ arg_type = func .arg_types [0 ]
1558+ if defn .is_class or defn .name == "__new__" :
1559+ ref_type = mypy .types .TypeType .make_normalized (ref_type )
1560+ if is_same_type (arg_type , ref_type ):
1561+ return True
1562+
1563+ # This level of erasure matches the one in checkmember.check_self_arg(),
1564+ # better keep these two checks consistent.
1565+ erased = get_proper_type (erase_typevars (erase_to_bound (arg_type )))
1566+ if not is_subtype (ref_type , erased , ignore_type_params = True ):
1567+ if (
1568+ isinstance (erased , Instance )
1569+ and erased .type .is_protocol
1570+ or isinstance (erased , TypeType )
1571+ and isinstance (erased .item , Instance )
1572+ and erased .item .type .is_protocol
1573+ ):
1574+ # We allow the explicit self-type to be not a supertype of
1575+ # the current class if it is a protocol. For such cases
1576+ # the consistency check will be performed at call sites.
1577+ msg = None
1578+ elif func .arg_names [0 ] in {"self" , "cls" }:
1579+ msg = message_registry .ERASED_SELF_TYPE_NOT_SUPERTYPE .format (
1580+ erased .str_with_options (self .options ), ref_type .str_with_options (self .options )
1581+ )
1582+ else :
1583+ msg = message_registry .MISSING_OR_INVALID_SELF_TYPE
1584+ if msg :
1585+ self .fail (msg , defn )
1586+ return True
1587+
15641588 def is_var_redefined_in_outer_context (self , v : Var , after_line : int ) -> bool :
15651589 """Can the variable be assigned to at module top level or outer function?
15661590
@@ -5298,6 +5322,7 @@ def visit_decorator_inner(
52985322 )
52995323 if non_trivial_decorator :
53005324 self .check_untyped_after_decorator (sig , e .func )
5325+ self .require_correct_self_argument (sig , e .func )
53015326 sig = set_callable_name (sig , e .func )
53025327 e .var .type = sig
53035328 e .var .is_ready = True
0 commit comments