diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index ecbb356f7b4d3..0ba58694792e2 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -315,7 +315,11 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> self.check_protocol_issubclass(e) if isinstance(ret_type, UninhabitedType) and not ret_type.ambiguous: self.chk.binder.unreachable() - if not allow_none_return and self.always_returns_none(e.callee): + # Warn on calls to functions that always return None. The check + # of ret_type is both a common-case optimization and prevents reporting + # the error in dynamic functions (where it will be Any). + if (not allow_none_return and isinstance(ret_type, NoneTyp) + and self.always_returns_none(e.callee)): self.chk.msg.does_not_return_value(callee_type, e) return AnyType(TypeOfAny.from_error) return ret_type diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 890d0be2dc188..876a5fe43f0ce 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2376,3 +2376,10 @@ def Y(x: Optional[str] = X(x_in)): ... xx: Optional[int] = X(x_in) [out] + +[case testNoComplainNoneReturnFromUntyped] +def foo() -> None: + pass + +def lol(): + x = foo()