reassignment of a `TypeAliasType` should not be evaluated as type expression
Unsurpringly, reassigning some generic TypeAliasType named A as B = A is not the same as subscripting it as B = A[Any]:
>>> type A[T] = T | str
>>> B = A
>>> type(A)
<class 'typing.TypeAliasType'>
>>> type(B)
<class 'typing.TypeAliasType'>
>>> A is B
True
Mypy's behavior (on master and 1.18.2) contradicts this:
type A[T] = T | T # ✔️ true negative
B = A # ❌ false positive: Missing type parameters for generic type "A" [type-arg]
reveal_type(A) # ✔️ mypy: "typing.TypeAliasType", runtime: "typing.TypeAliasType"
reveal_type(B) # ❌ mypy: "types.UnionType[Any, Any]", runtime: "typing.TypeAliasType"
https://mypy-play.net/?mypy=latest&python=3.12&flags=strict&gist=962d28cd59eff168c9cd2057e9f18f88
The error at line 2 is only reported in strict mode, so if you don't use that, I can imagine that it can be rather difficult to debug.
I realize that mypy interprets B = A as if it's B: TypeAlias = A, and it's not like there's nothing to be said for that. But I think that it's rather unlikely that a someone using the type keyword would expect that omitting it would result in the exact same behavior.
For _: TypeAlias that's a different story, and is currently working fine IMO; so I'm purely talking about TypeAliasType here. And given the differences in runtime semantics between the two, I think it's fair to treat them differently.
p.s. congratz with the 20k stars!
Hi @jorenham sir,
I would like to fix this.
I've traced the issue to mypy/semanal.py. Currently, is_type_ref returns True for the bare generic TypeAliasType, which forces the assignment to be evaluated as a new type alias definition (triggering the [type-arg] error) instead of a variable assignment.
I propose modifying is_type_ref to return False specifically when a generic PEP 695 alias is used without arguments. This ensures the analyzer treats it as a standard variable assignment, matching runtime behavior.
Does this sound like the right approach?
Thanks for your response, Paresh. To me that sounds like the right approach. But before investing your time in this, maybe we should wait a bit and see if a mypy maintainer has something to say about this.