From 90feab94738067084af529e0e8d19c7292079727 Mon Sep 17 00:00:00 2001 From: "Kai (Kazuya Ito)" Date: Thu, 5 Mar 2026 00:46:25 +0900 Subject: [PATCH 1/2] Correct `process_typevar_parameters()`, their relates and error message --- mypy/semanal.py | 38 +++++++++++++++--------------- test-data/unit/semanal-errors.test | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 5c8a5e03561b0..8f3268a076f9d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4740,7 +4740,7 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> bool: n_values = call.arg_kinds[1:].count(ARG_POS) values = self.analyze_value_types(call.args[1 : 1 + n_values]) - res = self.process_typevar_parameters( + res = self.process_typevar_arguments( call.args[1 + n_values :], call.arg_names[1 + n_values :], call.arg_kinds[1 + n_values :], @@ -4881,7 +4881,7 @@ def get_typevarlike_declaration( return None return call - def process_typevar_parameters( + def process_typevar_arguments( self, args: list[Expression], names: list[str | None], @@ -4894,38 +4894,38 @@ def process_typevar_parameters( contravariant = False upper_bound: Type = self.object_type() default: Type = AnyType(TypeOfAny.from_omitted_generics) - for param_value, param_name, param_kind in zip(args, names, kinds): - if not param_kind.is_named(): + for arg_value, arg_name, arg_kind in zip(args, names, kinds): + if not arg_kind.is_named(): self.fail(message_registry.TYPEVAR_UNEXPECTED_ARGUMENT, context) return None - if param_name == "covariant": - if isinstance(param_value, NameExpr) and param_value.name in ("True", "False"): - covariant = param_value.name == "True" + if arg_name == "covariant": + if isinstance(arg_value, NameExpr) and arg_value.name in ("True", "False"): + covariant = arg_value.name == "True" else: self.fail(message_registry.TYPEVAR_VARIANCE_DEF.format("covariant"), context) return None - elif param_name == "contravariant": - if isinstance(param_value, NameExpr) and param_value.name in ("True", "False"): - contravariant = param_value.name == "True" + elif arg_name == "contravariant": + if isinstance(arg_value, NameExpr) and arg_value.name in ("True", "False"): + contravariant = arg_value.name == "True" else: self.fail( message_registry.TYPEVAR_VARIANCE_DEF.format("contravariant"), context ) return None - elif param_name == "bound": + elif arg_name == "bound": if has_values: - self.fail("TypeVar cannot have both values and an upper bound", context) + self.fail("TypeVar cannot have both constraints and bound", context) return None - tv_arg = self.get_typevarlike_argument("TypeVar", param_name, param_value, context) + tv_arg = self.get_typevarlike_argument("TypeVar", arg_name, arg_value, context) if tv_arg is None: return None upper_bound = tv_arg - elif param_name == "default": + elif arg_name == "default": tv_arg = self.get_typevarlike_argument( - "TypeVar", param_name, param_value, context, allow_unbound_tvars=True + "TypeVar", arg_name, arg_value, context, allow_unbound_tvars=True ) default = tv_arg or AnyType(TypeOfAny.from_error) - elif param_name == "values": + elif arg_name == "values": # Probably using obsolete syntax with values=(...). Explain the current syntax. self.fail('TypeVar "values" argument not supported', context) self.fail( @@ -4934,7 +4934,7 @@ def process_typevar_parameters( return None else: self.fail( - f'{message_registry.TYPEVAR_UNEXPECTED_ARGUMENT}: "{param_name}"', context + f'{message_registry.TYPEVAR_UNEXPECTED_ARGUMENT}: "{arg_name}"', context ) return None @@ -5063,7 +5063,7 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: # PEP 612 reserves the right to define bound, covariant and contravariant arguments to # ParamSpec in a later PEP. If and when that happens, we should do something - # on the lines of process_typevar_parameters + # on the lines of process_typevar_arguments if not call.analyzed: paramspec_var = ParamSpecExpr( @@ -5178,7 +5178,7 @@ def analyze_value_types(self, items: list[Expression]) -> list[Type]: ) if analyzed is None: # Type variables are special: we need to place them in the symbol table - # soon, even if some value is not ready yet, see process_typevar_parameters() + # soon, even if some value is not ready yet, see process_typevar_arguments() # for an example. analyzed = PlaceholderType(None, [], node.line) if has_type_vars(analyzed): diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 40db0537c413e..3ec82950a115f 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1025,7 +1025,7 @@ k = TypeVar('k', contravariant=1) # E: TypeVar "contravariant" may only be a lit [case testMoreInvalidTypevarArguments] from typing import TypeVar -T = TypeVar('T', int, str, bound=bool) # E: TypeVar cannot have both values and an upper bound +T = TypeVar('T', int, str, bound=bool) # E: TypeVar cannot have both constraints and bound S = TypeVar('S', covariant=True, contravariant=True) \ # E: TypeVar cannot be both covariant and contravariant [builtins fixtures/bool.pyi] From 452122845011446a4f95e89657725061a54414f7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:00:10 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/semanal.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8f3268a076f9d..d4119e99cafe8 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4933,9 +4933,7 @@ def process_typevar_arguments( ) return None else: - self.fail( - f'{message_registry.TYPEVAR_UNEXPECTED_ARGUMENT}: "{arg_name}"', context - ) + self.fail(f'{message_registry.TYPEVAR_UNEXPECTED_ARGUMENT}: "{arg_name}"', context) return None if covariant and contravariant: