6363 ARG_STAR ,
6464 CONTRAVARIANT ,
6565 COVARIANT ,
66+ FUNC_NO_INFO ,
6667 GDEF ,
6768 IMPLICITLY_ABSTRACT ,
6869 INVARIANT ,
6970 IS_ABSTRACT ,
7071 LDEF ,
7172 LITERAL_TYPE ,
7273 MDEF ,
74+ NOT_ABSTRACT ,
7375 AssertStmt ,
7476 AssignmentExpr ,
7577 AssignmentStmt ,
@@ -620,7 +622,7 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
620622 self .visit_decorator (cast (Decorator , defn .items [0 ]))
621623 for fdef in defn .items :
622624 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 )
624626 if fdef .func .abstract_status in (IS_ABSTRACT , IMPLICITLY_ABSTRACT ):
625627 num_abstract += 1
626628 if num_abstract not in (0 , len (defn .items )):
@@ -987,7 +989,11 @@ def _visit_func_def(self, defn: FuncDef) -> None:
987989 )
988990
989991 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 ,
991997 ) -> None :
992998 """Type check a function.
993999
@@ -1001,7 +1007,7 @@ def check_func_item(
10011007 typ = type_override .copy_modified (line = typ .line , column = typ .column )
10021008 if isinstance (typ , CallableType ):
10031009 with self .enter_attribute_inference_context ():
1004- self .check_func_def (defn , typ , name )
1010+ self .check_func_def (defn , typ , name , allow_empty )
10051011 else :
10061012 raise RuntimeError ("Not supported" )
10071013
@@ -1018,7 +1024,9 @@ def enter_attribute_inference_context(self) -> Iterator[None]:
10181024 yield None
10191025 self .inferred_attribute_types = old_types
10201026
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 :
10221030 """Type check a function definition."""
1023
178F
1031 # Expand type variables with value restrictions to ordinary types.
10241032 expanded = self .expand_typevars (defn , typ )
@@ -1190,7 +1198,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str | None) ->
11901198 self .accept (item .body )
11911199 unreachable = self .binder .is_unreachable ()
11921200
1193- if not unreachable and not body_is_trivial :
1201+ if not unreachable :
11941202 if defn .is_generator or is_named_instance (
11951203 self .return_types [- 1 ], "typing.AwaitableGenerator"
11961204 ):
@@ -1203,28 +1211,79 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str | None) ->
12031211 return_type = self .return_types [- 1 ]
12041212 return_type = get_proper_type (return_type )
12051213
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+
12061252 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
12091257 ):
12101258 # 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.
12131260 if isinstance (return_type , UninhabitedType ):
12141261 # This is a NoReturn function
1215- self . fail ( message_registry .INVALID_IMPLICIT_RETURN , defn )
1262+ msg = message_registry .INVALID_IMPLICIT_RETURN
12161263 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 )
12191274 # 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 )
12281287
12291288 self .return_types .pop ()
12301289
@@ -6125,9 +6184,17 @@ def fail(
61256184 self .msg .fail (msg , context , code = code )
61266185
61276186 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 ,
61296193 ) -> None :
61306194 """Produce a note."""
6195+ if isinstance (msg , ErrorMessage ):
6196+ self .msg .note (msg .value , context , code = msg .code )
6197+ return
61316198 self .msg .note (msg , context , offset = offset , code = code )
61326199
61336200 def iterable_item_type (self , instance : Instance ) -> Type :
0 commit comments