I think most of these why-nots can be resolved if we allow TypeExpr-specific constructors. This should not create much obfuscation for the syntax because these statements would otherwise not be valid TypeExpr anyway.
It also requires very minimal changes to the documentation because on user side these are very natural and intuitive syntaxes, likely aligned with their expectations.
For example:
1 => int(1) # Normal expr
1 => Literal[1] # TypeExpr
(A, B) => tuple((A, B)) # Normal expr
(A, B) => Tuple[A, B] # TypeExpr
{"a": int} => dict({"a": int}) # Normal expr
{"a": int} => TypedDict[...] # TypeExpr
By “TypeExpr-specific constructors” I mean python interpreter will invoke typing-specific constructor on these expressions during byte code generation.
For the “Literal” example, a deal-breaker would be recursion hell. But I bet there is a solution out there.
1 => Literal[1] => Literal[Literal[1]] => ...
Upon second thought, as long as user adheres to the new syntax (i.e. 1
instead of Literal[1]
), there will be no recursion at all. Worst case is Literal[1]
expanded to Literal[Literal[1]]
- which is fine.
Another deal breaker: string literals conflicts with forward references. Possible solution will be use different types of quotes to distinguish them, but I anticipate a ton of opinions against it.
If I’ve involved in the discussion for forward reference, I guess one proposal I would give is to re-enable back-qoutes for deferred expression. This might also benifit defer-expressions. But it feels too late to even open up such discussion.