From 4ef0c09d7d13cec4db8db3922e96bf4a9a140a39 Mon Sep 17 00:00:00 2001 From: "Kai (Kazuya Ito)" Date: Tue, 3 Mar 2026 11:17:37 +0900 Subject: [PATCH 1/2] Clarify error message for TypeVar function --- mypy/message_registry.py | 2 +- test-data/unit/check-classes.test | 2 +- test-data/unit/check-errorcodes.test | 2 +- test-data/unit/check-generics.test | 10 +++++----- test-data/unit/check-inference.test | 4 ++-- test-data/unit/check-parameter-specification.test | 2 +- test-data/unit/check-selftype.test | 2 +- test-data/unit/check-typevar-unbound.test | 6 +++--- test-data/unit/check-unreachable-code.test | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 9de31514b6bd1..6d0f7abec9dbe 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -196,7 +196,7 @@ def with_additional_msg(self, info: str) -> ErrorMessage: TYPEVAR_ARG_MUST_BE_TYPE: Final = '{} "{}" must be a type' TYPEVAR_UNEXPECTED_ARGUMENT: Final = 'Unexpected argument to "TypeVar()"' UNBOUND_TYPEVAR: Final = ( - "A function returning TypeVar should receive at least one argument containing the same TypeVar" + "A function returning TypeVar should have at least one same TypeVar parameter" ) TYPE_PARAMETERS_SHOULD_BE_DECLARED: Final = ( "All type parameters should be declared ({} not declared)" diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 5a66eff2bd3b7..074c4b3022a63 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -3716,7 +3716,7 @@ def error(u_c: Type[U]) -> P: # Error here, see below return new_pro(u_c) # Error here, see below [out] main:11: note: Revealed type is "__main__.WizUser" -main:12: error: A function returning TypeVar should receive at least one argument containing the same TypeVar +main:12: error: A function returning TypeVar should have at least one same TypeVar parameter main:12: note: Consider using the upper bound "ProUser" instead main:13: error: Value of type variable "P" of "new_pro" cannot be "U" main:13: error: Incompatible return value type (got "U", expected "P") diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index ba2f23fd72940..5ad49641ac9ba 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -284,7 +284,7 @@ z: y # E: Variable "__main__.y" is not valid as a type [valid-type] \ from typing import TypeVar T = TypeVar('T') -def f() -> T: pass # E: A function returning TypeVar should receive at least one argument containing the same TypeVar [type-var] +def f() -> T: pass # E: A function returning TypeVar should have at least one same TypeVar parameter [type-var] x = f() # E: Need type annotation for "x" [var-annotated] y = [] # E: Need type annotation for "y" (hint: "y: list[] = ...") [var-annotated] [builtins fixtures/list.pyi] diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 26d709850c1e1..cb8adafe9f483 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -1599,9 +1599,9 @@ A = TypeVar('A') B = TypeVar('B') def f1(x: A) -> A: ... -def f2(x: A) -> B: ... # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def f2(x: A) -> B: ... # E: A function returning TypeVar should have at least one same TypeVar parameter def f3(x: B) -> B: ... -def f4(x: int) -> A: ... # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def f4(x: int) -> A: ... # E: A function returning TypeVar should have at least one same TypeVar parameter y1 = f1 if int(): @@ -1650,8 +1650,8 @@ B = TypeVar('B') T = TypeVar('T') def outer(t: T) -> None: def f1(x: A) -> A: ... - def f2(x: A) -> B: ... # E: A function returning TypeVar should receive at least one argument containing the same TypeVar - def f3(x: T) -> A: ... # E: A function returning TypeVar should receive at least one argument containing the same TypeVar + def f2(x: A) -> B: ... # E: A function returning TypeVar should have at least one same TypeVar parameter + def f3(x: T) -> A: ... # E: A function returning TypeVar should have at least one same TypeVar parameter def f4(x: A) -> T: ... def f5(x: T) -> T: ... @@ -1818,7 +1818,7 @@ from typing import TypeVar A = TypeVar('A') B = TypeVar('B') def f1(x: int, y: A) -> A: ... -def f2(x: int, y: A) -> B: ... # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def f2(x: int, y: A) -> B: ... # E: A function returning TypeVar should have at least one same TypeVar parameter def f3(x: A, y: B) -> B: ... g = f1 g = f2 diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 22edd12b0c4ca..12a26e9bb6bd4 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -590,7 +590,7 @@ def ff() -> None: x = f() # E: Need type annotation for "x" reveal_type(x) # N: Revealed type is "Any" -def f() -> T: pass # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def f() -> T: pass # E: A function returning TypeVar should have at least one same TypeVar parameter def g(a: T) -> None: pass g(None) # Ok @@ -2693,7 +2693,7 @@ def main() -> None: [case testDontMarkUnreachableAfterInferenceUninhabited] from typing import TypeVar T = TypeVar('T') -def f() -> T: pass # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def f() -> T: pass # E: A function returning TypeVar should have at least one same TypeVar parameter class C: x = f() # E: Need type annotation for "x" diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index b0808105a3858..1d931b5f570de 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1161,7 +1161,7 @@ def callback(func: Callable[[Any], Any]) -> None: ... class Job(Generic[P]): ... @callback -def run_job(job: Job[...]) -> T: ... # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def run_job(job: Job[...]) -> T: ... # E: A function returning TypeVar should have at least one same TypeVar parameter [builtins fixtures/tuple.pyi] [case testTupleAndDictOperationsOnParamSpecArgsAndKwargs] diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index c157200352562..79e93833d5f58 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1541,7 +1541,7 @@ class C: def meth(cls) -> Self: ... @staticmethod def bad() -> Self: ... # E: Static methods cannot use Self type \ - # E: A function returning TypeVar should receive at least one argument containing the same TypeVar \ + # E: A function returning TypeVar should have at least one same TypeVar parameter \ # N: Consider using the upper bound "C" instead class D(C): ... diff --git a/test-data/unit/check-typevar-unbound.test b/test-data/unit/check-typevar-unbound.test index 79d326f9fedf3..cf68341987f67 100644 --- a/test-data/unit/check-typevar-unbound.test +++ b/test-data/unit/check-typevar-unbound.test @@ -3,19 +3,19 @@ from typing import TypeVar T = TypeVar('T') -def f() -> T: # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def f() -> T: # E: A function returning TypeVar should have at least one same TypeVar parameter ... f() U = TypeVar('U', bound=int) -def g() -> U: # E: A function returning TypeVar should receive at least one argument containing the same TypeVar \ +def g() -> U: # E: A function returning TypeVar should have at least one same TypeVar parameter \ # N: Consider using the upper bound "int" instead ... V = TypeVar('V', int, str) -def h() -> V: # E: A function returning TypeVar should receive at least one argument containing the same TypeVar +def h() -> V: # E: A function returning TypeVar should have at least one same TypeVar parameter ... [case testInnerFunctionTypeVar] diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index 22c4c80916cbe..992a8c687acc3 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -1567,7 +1567,7 @@ from typing import TypeVar T = TypeVar("T") class Foo: - def __setitem__(self, key: str, value: str) -> T: # E: A function returning TypeVar should receive at least one argument containing the same TypeVar + def __setitem__(self, key: str, value: str) -> T: # E: A function returning TypeVar should have at least one same TypeVar parameter raise Exception def f() -> None: From dfaec6c755702232355fc52521f4df305260c911 Mon Sep 17 00:00:00 2001 From: "Kai (Kazuya Ito)" Date: Wed, 4 Mar 2026 09:49:05 +0900 Subject: [PATCH 2/2] More clarify error message for TypeVar function --- mypy/message_registry.py | 2 +- test-data/unit/check-classes.test | 2 +- test-data/unit/check-errorcodes.test | 2 +- test-data/unit/check-generics.test | 10 +++++----- test-data/unit/check-inference.test | 4 ++-- test-data/unit/check-parameter-specification.test | 2 +- test-data/unit/check-selftype.test | 2 +- test-data/unit/check-typevar-unbound.test | 6 +++--- test-data/unit/check-unreachable-code.test | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 6d0f7abec9dbe..ea8ff00b75346 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -196,7 +196,7 @@ def with_additional_msg(self, info: str) -> ErrorMessage: TYPEVAR_ARG_MUST_BE_TYPE: Final = '{} "{}" must be a type' TYPEVAR_UNEXPECTED_ARGUMENT: Final = 'Unexpected argument to "TypeVar()"' UNBOUND_TYPEVAR: Final = ( - "A function returning TypeVar should have at least one same TypeVar parameter" + "A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations" ) TYPE_PARAMETERS_SHOULD_BE_DECLARED: Final = ( "All type parameters should be declared ({} not declared)" diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 074c4b3022a63..1c7cb0aeea0c9 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -3716,7 +3716,7 @@ def error(u_c: Type[U]) -> P: # Error here, see below return new_pro(u_c) # Error here, see below [out] main:11: note: Revealed type is "__main__.WizUser" -main:12: error: A function returning TypeVar should have at least one same TypeVar parameter +main:12: error: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations main:12: note: Consider using the upper bound "ProUser" instead main:13: error: Value of type variable "P" of "new_pro" cannot be "U" main:13: error: Incompatible return value type (got "U", expected "P") diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 5ad49641ac9ba..9af08e9b82d9d 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -284,7 +284,7 @@ z: y # E: Variable "__main__.y" is not valid as a type [valid-type] \ from typing import TypeVar T = TypeVar('T') -def f() -> T: pass # E: A function returning TypeVar should have at least one same TypeVar parameter [type-var] +def f() -> T: pass # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations [type-var] x = f() # E: Need type annotation for "x" [var-annotated] y = [] # E: Need type annotation for "y" (hint: "y: list[] = ...") [var-annotated] [builtins fixtures/list.pyi] diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index cb8adafe9f483..c78b1665e6495 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -1599,9 +1599,9 @@ A = TypeVar('A') B = TypeVar('B') def f1(x: A) -> A: ... -def f2(x: A) -> B: ... # E: A function returning TypeVar should have at least one same TypeVar parameter +def f2(x: A) -> B: ... # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations def f3(x: B) -> B: ... -def f4(x: int) -> A: ... # E: A function returning TypeVar should have at least one same TypeVar parameter +def f4(x: int) -> A: ... # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations y1 = f1 if int(): @@ -1650,8 +1650,8 @@ B = TypeVar('B') T = TypeVar('T') def outer(t: T) -> None: def f1(x: A) -> A: ... - def f2(x: A) -> B: ... # E: A function returning TypeVar should have at least one same TypeVar parameter - def f3(x: T) -> A: ... # E: A function returning TypeVar should have at least one same TypeVar parameter + def f2(x: A) -> B: ... # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations + def f3(x: T) -> A: ... # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations def f4(x: A) -> T: ... def f5(x: T) -> T: ... @@ -1818,7 +1818,7 @@ from typing import TypeVar A = TypeVar('A') B = TypeVar('B') def f1(x: int, y: A) -> A: ... -def f2(x: int, y: A) -> B: ... # E: A function returning TypeVar should have at least one same TypeVar parameter +def f2(x: int, y: A) -> B: ... # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations def f3(x: A, y: B) -> B: ... g = f1 g = f2 diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 12a26e9bb6bd4..d402dc8e8c942 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -590,7 +590,7 @@ def ff() -> None: x = f() # E: Need type annotation for "x" reveal_type(x) # N: Revealed type is "Any" -def f() -> T: pass # E: A function returning TypeVar should have at least one same TypeVar parameter +def f() -> T: pass # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations def g(a: T) -> None: pass g(None) # Ok @@ -2693,7 +2693,7 @@ def main() -> None: [case testDontMarkUnreachableAfterInferenceUninhabited] from typing import TypeVar T = TypeVar('T') -def f() -> T: pass # E: A function returning TypeVar should have at least one same TypeVar parameter +def f() -> T: pass # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations class C: x = f() # E: Need type annotation for "x" diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 1d931b5f570de..950697d622c3d 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1161,7 +1161,7 @@ def callback(func: Callable[[Any], Any]) -> None: ... class Job(Generic[P]): ... @callback -def run_job(job: Job[...]) -> T: ... # E: A function returning TypeVar should have at least one same TypeVar parameter +def run_job(job: Job[...]) -> T: ... # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations [builtins fixtures/tuple.pyi] [case testTupleAndDictOperationsOnParamSpecArgsAndKwargs] diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index 79e93833d5f58..32094b2c2d47a 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1541,7 +1541,7 @@ class C: def meth(cls) -> Self: ... @staticmethod def bad() -> Self: ... # E: Static methods cannot use Self type \ - # E: A function returning TypeVar should have at least one same TypeVar parameter \ + # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations \ # N: Consider using the upper bound "C" instead class D(C): ... diff --git a/test-data/unit/check-typevar-unbound.test b/test-data/unit/check-typevar-unbound.test index cf68341987f67..137da1299790a 100644 --- a/test-data/unit/check-typevar-unbound.test +++ b/test-data/unit/check-typevar-unbound.test @@ -3,19 +3,19 @@ from typing import TypeVar T = TypeVar('T') -def f() -> T: # E: A function returning TypeVar should have at least one same TypeVar parameter +def f() -> T: # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations ... f() U = TypeVar('U', bound=int) -def g() -> U: # E: A function returning TypeVar should have at least one same TypeVar parameter \ +def g() -> U: # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations \ # N: Consider using the upper bound "int" instead ... V = TypeVar('V', int, str) -def h() -> V: # E: A function returning TypeVar should have at least one same TypeVar parameter +def h() -> V: # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations ... [case testInnerFunctionTypeVar] diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index 992a8c687acc3..1fc3a33bb8964 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -1567,7 +1567,7 @@ from typing import TypeVar T = TypeVar("T") class Foo: - def __setitem__(self, key: str, value: str) -> T: # E: A function returning TypeVar should have at least one same TypeVar parameter + def __setitem__(self, key: str, value: str) -> T: # E: A function returning TypeVar should use that same TypeVar somewhere in its parameter annotations raise Exception def f() -> None: