diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 1f75ac54d525..a865a4dd1532 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -741,7 +741,7 @@ returns ``None``: # OK: we don't do anything with the return value f() - # Error: "f" does not return a value [func-returns-value] + # Error: "f" does not return a value (it only ever returns None) [func-returns-value] if f(): print("not false") diff --git a/mypy/messages.py b/mypy/messages.py index cda4cda25ee4..4b71bd876dcc 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1021,18 +1021,11 @@ def duplicate_argument_value(self, callee: CallableType, index: int, context: Co def does_not_return_value(self, callee_type: Type | None, context: Context) -> None: """Report an error about use of an unusable type.""" - name: str | None = None callee_type = get_proper_type(callee_type) - if isinstance(callee_type, FunctionLike): - name = callable_name(callee_type) - if name is not None: - self.fail( - f"{capitalize(name)} does not return a value", - context, - code=codes.FUNC_RETURNS_VALUE, - ) - else: - self.fail("Function does not return a value", context, code=codes.FUNC_RETURNS_VALUE) + callee_name = callable_name(callee_type) if isinstance(callee_type, FunctionLike) else None + name = callee_name or "Function" + message = f"{name} does not return a value (it only ever returns None)" + self.fail(message, context, code=codes.FUNC_RETURNS_VALUE) def deleted_as_rvalue(self, typ: DeletedType, context: Context) -> None: """Report an error about using an deleted type as an rvalue.""" diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 796e1c1ea98e..df14e328ed72 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -553,15 +553,15 @@ from typing import Callable def f() -> None: pass -x = f() # E: "f" does not return a value [func-returns-value] +x = f() # E: "f" does not return a value (it only ever returns None) [func-returns-value] class A: def g(self) -> None: pass -y = A().g() # E: "g" of "A" does not return a value [func-returns-value] +y = A().g() # E: "g" of "A" does not return a value (it only ever returns None) [func-returns-value] c: Callable[[], None] -z = c() # E: Function does not return a value [func-returns-value] +z = c() # E: Function does not return a value (it only ever returns None) [func-returns-value] [case testErrorCodeInstantiateAbstract] from abc import abstractmethod diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index c213255997f8..a3c1bc8795f2 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1079,15 +1079,15 @@ class A: a: A o: object if int(): - a = f() # E: "f" does not return a value + a = f() # E: "f" does not return a value (it only ever returns None) if int(): - o = a() # E: Function does not return a value + o = a() # E: Function does not return a value (it only ever returns None) if int(): - o = A().g(a) # E: "g" of "A" does not return a value + o = A().g(a) # E: "g" of "A" does not return a value (it only ever returns None) if int(): - o = A.g(a, a) # E: "g" of "A" does not return a value -A().g(f()) # E: "f" does not return a value -x: A = f() # E: "f" does not return a value + o = A.g(a, a) # E: "g" of "A" does not return a value (it only ever returns None) +A().g(f()) # E: "f" does not return a value (it only ever returns None) +x: A = f() # E: "f" does not return a value (it only ever returns None) f() A().g(a) [builtins fixtures/tuple.pyi] @@ -1096,15 +1096,15 @@ A().g(a) import typing def f() -> None: pass -if f(): # E: "f" does not return a value +if f(): # E: "f" does not return a value (it only ever returns None) pass -elif f(): # E: "f" does not return a value +elif f(): # E: "f" does not return a value (it only ever returns None) pass -while f(): # E: "f" does not return a value +while f(): # E: "f" does not return a value (it only ever returns None) pass def g() -> object: - return f() # E: "f" does not return a value -raise f() # E: "f" does not return a value + return f() # E: "f" does not return a value (it only ever returns None) +raise f() # E: "f" does not return a value (it only ever returns None) [builtins fixtures/exception.pyi] [case testNoneReturnTypeWithExpressions] @@ -1115,13 +1115,13 @@ class A: def __add__(self, x: 'A') -> 'A': pass a: A -[f()] # E: "f" does not return a value -f() + a # E: "f" does not return a value -a + f() # E: "f" does not return a value -f() == a # E: "f" does not return a value -a != f() # E: "f" does not return a value +[f()] # E: "f" does not return a value (it only ever returns None) +f() + a # E: "f" does not return a value (it only ever returns None) +a + f() # E: "f" does not return a value (it only ever returns None) +f() == a # E: "f" does not return a value (it only ever returns None) +a != f() # E: "f" does not return a value (it only ever returns None) cast(A, f()) -f().foo # E: "f" does not return a value +f().foo # E: "f" does not return a value (it only ever returns None) [builtins fixtures/list.pyi] [case testNoneReturnTypeWithExpressions2] @@ -1134,14 +1134,14 @@ class A: a: A b: bool -f() in a # E: "f" does not return a value # E: Unsupported right operand type for in ("A") -a < f() # E: "f" does not return a value -f() <= a # E: "f" does not return a value -a in f() # E: "f" does not return a value --f() # E: "f" does not return a value -not f() # E: "f" does not return a value -f() and b # E: "f" does not return a value -b or f() # E: "f" does not return a value +f() in a # E: "f" does not return a value (it only ever returns None) # E: Unsupported right operand type for in ("A") +a < f() # E: "f" does not return a value (it only ever returns None) +f() <= a # E: "f" does not return a value (it only ever returns None) +a in f() # E: "f" does not return a value (it only ever returns None) +-f() # E: "f" does not return a value (it only ever returns None) +not f() # E: "f" does not return a value (it only ever returns None) +f() and b # E: "f" does not return a value (it only ever returns None) +b or f() # E: "f" does not return a value (it only ever returns None) [builtins fixtures/bool.pyi] @@ -1441,7 +1441,7 @@ if int(): [case testConditionalExpressionWithEmptyCondition] import typing def f() -> None: pass -x = 1 if f() else 2 # E: "f" does not return a value +x = 1 if f() else 2 # E: "f" does not return a value (it only ever returns None) [case testConditionalExpressionWithSubtyping] import typing @@ -1504,7 +1504,7 @@ from typing import List, Union x = [] y = "" x.append(y) if bool() else x.append(y) -z = x.append(y) if bool() else x.append(y) # E: "append" of "list" does not return a value +z = x.append(y) if bool() else x.append(y) # E: "append" of "list" does not return a value (it only ever returns None) [builtins fixtures/list.pyi] -- Special cases @@ -1604,7 +1604,7 @@ def f(x: int) -> None: [builtins fixtures/for.pyi] [out] main:1: error: The return type of a generator function should be "Generator" or one of its supertypes -main:2: error: "f" does not return a value +main:2: error: "f" does not return a value (it only ever returns None) main:2: error: Argument 1 to "f" has incompatible type "str"; expected "int" [case testYieldExpressionWithNone] @@ -1624,7 +1624,7 @@ from typing import Iterator def f() -> Iterator[int]: yield 5 def g() -> Iterator[int]: - a = yield from f() # E: Function does not return a value + a = yield from f() # E: Function does not return a value (it only ever returns None) [case testYieldFromGeneratorHasValue] from typing import Iterator, Generator @@ -1639,12 +1639,12 @@ def g() -> Iterator[int]: [case testYieldFromTupleExpression] from typing import Generator def g() -> Generator[int, None, None]: - x = yield from () # E: Function does not return a value - x = yield from (0, 1, 2) # E: Function does not return a value + x = yield from () # E: Function does not return a value (it only ever returns None) + x = yield from (0, 1, 2) # E: Function does not return a value (it only ever returns None) x = yield from (0, "ERROR") # E: Incompatible types in "yield from" (actual type "object", expected type "int") \ - # E: Function does not return a value + # E: Function does not return a value (it only ever returns None) x = yield from ("ERROR",) # E: Incompatible types in "yield from" (actual type "str", expected type "int") \ - # E: Function does not return a value + # E: Function does not return a value (it only ever returns None) [builtins fixtures/tuple.pyi] -- dict(...) diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 4cc523a595d1..cd098a84d4d3 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -250,7 +250,7 @@ if int(): if int(): f = o # E: Incompatible types in assignment (expression has type "object", variable has type "Callable[[], None]") if int(): - f = f() # E: Function does not return a value + f = f() # E: Function does not return a value (it only ever returns None) if int(): f = f diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 36b028977591..f9a4d58c74af 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -33,8 +33,8 @@ class B: pass [case testLvarInitializedToVoid] import typing def f() -> None: - a = g() # E: "g" does not return a value - #b, c = g() # "g" does not return a value TODO + a = g() # E: "g" does not return a value (it only ever returns None) + #b, c = g() # "g" does not return a value (it only ever returns None) TODO def g() -> None: pass [out] @@ -1180,7 +1180,7 @@ for e, f in [[]]: # E: Need type annotation for "e" \ [case testForStatementInferenceWithVoid] def f() -> None: pass -for x in f(): # E: "f" does not return a value +for x in f(): # E: "f" does not return a value (it only ever returns None) pass [builtins fixtures/for.pyi] @@ -2118,7 +2118,7 @@ arr = [] arr.append(arr.append(1)) [builtins fixtures/list.pyi] [out] -main:3: error: "append" of "list" does not return a value +main:3: error: "append" of "list" does not return a value (it only ever returns None) -- Multipass -- --------- diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index ae247b0047f1..70f3c4486e14 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -361,9 +361,9 @@ def f() -> None: def g(x: Optional[int]) -> int: pass -x = f() # E: "f" does not return a value -f() + 1 # E: "f" does not return a value -g(f()) # E: "f" does not return a value +x = f() # E: "f" does not return a value (it only ever returns None) +f() + 1 # E: "f" does not return a value (it only ever returns None) +g(f()) # E: "f" does not return a value (it only ever returns None) [case testEmptyReturn] def f() -> None: diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index cff261774663..0e7c81edc498 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -169,8 +169,8 @@ class C(B): pass import typing def f() -> None: pass -(None, f()) # E: "f" does not return a value -(f(), None) # E: "f" does not return a value +(None, f()) # E: "f" does not return a value (it only ever returns None) +(f(), None) # E: "f" does not return a value (it only ever returns None) [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index 54546f3973b3..ef2c3c57fad5 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -52,8 +52,8 @@ c: C f(c) # E: Argument 1 to "f" has incompatible type "C"; expected "A" f(a, b, c) # E: Argument 3 to "f" has incompatible type "C"; expected "A" -f(g()) # E: "g" does not return a value -f(a, g()) # E: "g" does not return a value +f(g()) # E: "g" does not return a value (it only ever returns None) +f(a, g()) # E: "g" does not return a value (it only ever returns None) f() f(a) f(b) diff --git a/test-data/unit/pythoneval-asyncio.test b/test-data/unit/pythoneval-asyncio.test index 069374b9635c..4a185557495b 100644 --- a/test-data/unit/pythoneval-asyncio.test +++ b/test-data/unit/pythoneval-asyncio.test @@ -261,7 +261,7 @@ try: finally: loop.close() [out] -_program.py:11: error: Function does not return a value +_program.py:11: error: Function does not return a value (it only ever returns None) [case testErrorReturnIsNotTheSameType] from typing import Any