63
63
ARG_STAR ,
64
64
CONTRAVARIANT ,
65
65
COVARIANT ,
66
+ FUNC_NO_INFO ,
66
67
GDEF ,
67
68
IMPLICITLY_ABSTRACT ,
68
69
INVARIANT ,
69
70
IS_ABSTRACT ,
70
71
LDEF ,
71
72
LITERAL_TYPE ,
72
73
MDEF ,
74
+ NOT_ABSTRACT ,
73
75
AssertStmt ,
74
76
AssignmentExpr ,
75
77
AssignmentStmt ,
@@ -620,7 +622,7 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
620
622
self .visit_decorator (cast (Decorator , defn .items [0 ]))
621
623
for fdef in defn .items :
622
624
assert isinstance (fdef , Decorator )
623
- self .check_func_item (fdef .func , name = fdef .func .name )
625
+ self .check_func_item (fdef .func , name = fdef .func .name , allow_empty = True )
624
626
if fdef .func .abstract_status in (IS_ABSTRACT , IMPLICITLY_ABSTRACT ):
625
627
num_abstract += 1
626
628
if num_abstract not in (0 , len (defn .items )):
@@ -987,7 +989,11 @@ def _visit_func_def(self, defn: FuncDef) -> None:
987
989
)
988
990
989
991
def check_func_item (
990
- self , defn : FuncItem , type_override : CallableType | None = None , name : str | None = None
992
+ self ,
993
+ defn : FuncItem ,
994
+ type_override : CallableType | None = None ,
995
+ name : str | None = None ,
996
+ allow_empty : bool = False ,
991
997
) -> None :
992
998
"""Type check a function.
993
999
@@ -1001,7 +1007,7 @@ def check_func_item(
1001
1007
typ = type_override .copy_modified (line = typ .line , column = typ .column )
1002
1008
if isinstance (typ , CallableType ):
1003
1009
with self .enter_attribute_inference_context ():
1004
- self .check_func_def (defn , typ , name )
1010
+ self .check_func_def (defn , typ , name , allow_empty )
1005
1011
else :
1006
1012
raise RuntimeError ("Not supported" )
1007
1013
@@ -1018,7 +1024,9 @@ def enter_attribute_inference_context(self) -> Iterator[None]:
1018
1024
yield None
1019
1025
self .inferred_attribute_types = old_types
1020
1026
1021
- def check_func_def (self , defn : FuncItem , typ : CallableType , name : str | None ) -> None :
1027
+ def check_func_def (
1028
+ self , defn : FuncItem , typ : CallableType , name : str | None , allow_empty : bool = False
1029
+ ) -> None :
1022
1030
"""Type check a function definition."""
1023
1031
# Expand type variables with value restrictions to ordinary types.
1024
1032
expanded = self .expand_typevars (defn , typ )
@@ -1190,7 +1198,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str | None) ->
1190
1198
self .accept (item .body )
1191
1199
unreachable = self .binder .is_unreachable ()
1192
1200
1193
- if not unreachable and not body_is_trivial :
1201
+ if not unreachable :
1194
1202
if defn .is_generator or is_named_instance (
1195
1203
self .return_types [- 1 ], "typing.AwaitableGenerator"
1196
1204
):
@@ -1203,28 +1211,79 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str | None) ->
1203
1211
return_type = self .return_types [- 1 ]
1204
1212
return_type = get_proper_type (return_type )
1205
1213
1214
+ allow_empty = allow_empty or self .options .allow_empty_bodies
1215
+
1216
+ show_error = (
1217
+ not body_is_trivial
1218
+ or
1219
+ # Allow empty bodies for abstract methods, overloads, in tests and stubs.
1220
+ (
1221
+ not allow_empty
1222
+ and not (
1223
+ isinstance (defn , FuncDef ) and defn .abstract_status != NOT_ABSTRACT
1224
+ )
1225
+ and not self .is_stub
1226
+ )
1227
+ )
1228
+
1229
+ # Ignore plugin generated methods, these usually don't need any bodies.
1230
+ if defn .info is not FUNC_NO_INFO and (
1231
+ defn .name not in defn .info .names or defn .info .names [defn .name ].plugin_generated
1232
+ ):
1233
+ show_error = False
1234
+
1235
+ # Ignore also definitions that appear in `if TYPE_CHECKING: ...` blocks.
1236
+ # These can't be called at runtime anyway (similar to plugin-generated).
1237
+ if isinstance (defn , FuncDef ) and defn .is_mypy_only :
1238
+ show_error = False
1239
+
1240
+ # We want to minimize the fallout from checking empty bodies
1241
+ # that was absent in many mypy versions.
1242
+ if body_is_trivial and is_subtype (NoneType (), return_type ):
1243
+ show_error = False
1244
+
1245
+ may_be_abstract = (
1246
+ body_is_trivial
1247
+ and defn .info is not FUNC_NO_INFO
1248
+ and defn .info .metaclass_type is not None
1249
+ and defn .info .metaclass_type .type .has_base ("abc.ABCMeta" )
1250
+ )
1251
+
1206
1252
if self .options .warn_no_return :
1207
- if not self .current_node_deferred and not isinstance (
1208
- return_type , (NoneType , AnyType )
1253
+ if (
1254
+ not self .current_node_deferred
1255
+ and not isinstance (return_type , (NoneType , AnyType ))
1256
+ and show_error
1209
1257
):
1210
1258
# Control flow fell off the end of a function that was
1211
- # declared to return a non-None type and is not
1212
- # entirely pass/Ellipsis/raise NotImplementedError.
1259
+ # declared to return a non-None type.
1213
1260
if isinstance (return_type , UninhabitedType ):
1214
1261
# This is a NoReturn function
1215
- self . fail ( message_registry .INVALID_IMPLICIT_RETURN , defn )
1262
+ msg = message_registry .INVALID_IMPLICIT_RETURN
1216
1263
else :
1217
- self .fail (message_registry .MISSING_RETURN_STATEMENT , defn )
1218
- else :
1264
+ msg = message_registry .MISSING_RETURN_STATEMENT
1265
+ if body_is_trivial :
1266
+ msg = msg ._replace (code = codes .EMPTY_BODY )
1267
+ self .fail (msg , defn )
1268
+ if may_be_abstract :
1269
+ self .note (message_registry .EMPTY_BODY_ABSTRACT , defn )
1270
+ elif show_error :
1271
+ msg = message_registry .INCOMPATIBLE_RETURN_VALUE_TYPE
1272
+ if body_is_trivial :
1273
+ msg = msg ._replace (code = codes .EMPTY_BODY )
1219
1274
# similar to code in check_return_stmt
1220
- self .check_subtype (
1221
- subtype_label = "implicitly returns" ,
1222
- subtype = NoneType (),
1223
- supertype_label = "expected" ,
1224
- supertype = return_type ,
1225
- context = defn ,
1226
- msg = message_registry .INCOMPATIBLE_RETURN_VALUE_TYPE ,
1227
- )
1275
+ if (
1276
+ not self .check_subtype (
1277
+ subtype_label = "implicitly returns" ,
1278
+ subtype = NoneType (),
1279
+ supertype_label = "expected" ,
1280
+ supertype = return_type ,
1281
+ context = defn ,
1282
+ msg = msg ,
1283
+ )
1284
+ and may_be_abstract
1285
+ ):
1286
+ self .note (message_registry .EMPTY_BODY_ABSTRACT , defn )
1228
1287
1229
1288
self .return_types .pop ()
1230
1289
@@ -6125,9 +6184,17 @@ def fail(
6125
6184
self .msg .fail (msg , context , code = code )
6126
6185
6127
6186
def note (
6128
- self , msg : str , context : Context , offset : int = 0 , * , code : ErrorCode | None = None
6187
+ self ,
6188
+ msg : str | ErrorMessage ,
6189
+ context : Context ,
6190
+ offset : int = 0 ,
6191
+ * ,
6192
+ code : ErrorCode | None = None ,
6129
6193
) -> None :
6130
6194
"""Produce a note."""
6195
+ if isinstance (msg , ErrorMessage ):
6196
+ self .msg .note (msg .value , context , code = msg .code )
6197
+ return
6131
6198
self .msg .note (msg , context , offset = offset , code = code )
6132
6199
6133
6200
def iterable_item_type (self , instance : Instance ) -> Type :
0 commit comments