From b9823f6fe5f4701b36ed464143df6681bfbfb3b4 Mon Sep 17 00:00:00 2001 From: jetsetbrand Date: Fri, 28 Nov 2025 16:05:28 +0530 Subject: [PATCH 1/3] Fix: Treat bare generic TypeAliasType assignment as variable (Fixes #20308) --- mypy/semanal.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8179813c7171..f1260cf15efb 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3493,13 +3493,28 @@ def is_type_ref(self, rv: Expression, bare: bool = False) -> bool: else: valid_refs = type_constructors - if isinstance(rv.node, TypeAlias) or rv.fullname in valid_refs: + if isinstance(rv.node, TypeAlias): + # Fix for #20308: Reassignment of a generic TypeAliasType (PEP 695) + # should be evaluated as a variable assignment, not a type expression. + # This allows usage like `B = A` where `type A[T] = ...` without + # triggering "Missing type parameters" error. + if ( + bare + and rv.node.python_3_12_type_alias + and rv.node.alias_tvars + ): + return False return True + + if rv.fullname in valid_refs: + return True + if isinstance(rv.node, TypeInfo): if bare: return True # Assignment color = Color['RED'] defines a variable, not an alias. return not rv.node.is_enum + if isinstance(rv.node, Var): return rv.node.fullname in NEVER_NAMES From c1f3b1eefe0eff532a789537185509c5ae76bd81 Mon Sep 17 00:00:00 2001 From: jetsetbrand Date: Sat, 29 Nov 2025 10:44:38 +0530 Subject: [PATCH 2/3] Add regression test with typing-full fixture --- test-data/unit/check-python312.test | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index a67ed4abcffa..9ec55d194342 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -2237,3 +2237,14 @@ class D[*Ts](Generic[Unpack[Us]]): # E: Generic[...] base class is redundant \ # E: Can only use one type var tuple in a class def pass [builtins fixtures/tuple.pyi] + +[case testPep695GenericTypeAliasReassignment] +from typing import reveal_type + +type A[T] = T | str +B = A +reveal_type(B) +[out] +main:5: note: Revealed type is "typing.TypeAliasType" +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-full.pyi] From 9da85e6573987594795a0cd1e665d0b97b12d438 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 29 Nov 2025 05:19:05 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/semanal.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index f1260cf15efb..936d2ba2c9d4 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3498,11 +3498,7 @@ def is_type_ref(self, rv: Expression, bare: bool = False) -> bool: # should be evaluated as a variable assignment, not a type expression. # This allows usage like `B = A` where `type A[T] = ...` without # triggering "Missing type parameters" error. - if ( - bare - and rv.node.python_3_12_type_alias - and rv.node.alias_tvars - ): + if bare and rv.node.python_3_12_type_alias and rv.node.alias_tvars: return False return True