Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mypyc] Support Python 3.12 type alias syntax (PEP 695) #17384

Merged
merged 13 commits into from
Jun 17, 2024
Merged

Conversation

JukkaL
Copy link
Collaborator

@JukkaL JukkaL commented Jun 14, 2024

The main tricky bit is supporting uses of type alias objects at runtime. Python evaluates values of type aliases lazily, but there's no way to do this using public APIs, so we directly modify the TypeAliasType object that is used to represent a type alias at runtime in C. Unfortunately, this is fragile and will need to be updated each time CPython updates the internal representation of TypeAliasType objects.

Wrap the target of the type alias within a lambda expression, so that we can easily create the lazy compute function in mypyc. This also reflects how this is implemented in CPython.

Improve test stubs to avoid various false positives or confusing errors in tests when type checking runtime operations on types. This also makes some exisisting tests more realistic.

Follow-up to #17357.

Copy link
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG, but I have one question.

@@ -411,7 +411,9 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
result = self.alias_type_in_runtime_context(
node, ctx=e, alias_definition=e.is_alias_rvalue or lvalue
)
elif isinstance(node, (TypeVarExpr, ParamSpecExpr, TypeVarTupleExpr)):
elif isinstance(node, TypeVarExpr):
return self.named_type("typing.TypeVar")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this cause crashes on Python versions where TypeVar is not a proper class? And/or if it is imported from typing_extensions (e.g. by people who want the type variables with defaults)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeVar has been a class since at least 3.6, for what it's worth: https://github.com/python/cpython/blob/8d999cbf4adea053be6dbb612b9844635c4dfb8e/Lib/typing.py#L453.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeVar is defined unconditionally as a class in typeshed:

@final
class TypeVar:
    @property
    def __name__(self) -> str: ...
    @property
    def __bound__(self) -> Any | None: ...
    ...

Also on the oldest supported Python version (3.8) TypeVar is a class:

Python 3.8.10 (v3.8.10:3d8993a744, May  3 2021, 09:09:08)
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import TypeVar
>>> TypeVar
<class 'typing.TypeVar'>

But this won't be right if TypeVar is imported from typing_extensions. It probably won't usually make a difference, but it's possible to imagine runtime introspection use cases where mypy could get confused. But this wasn't properly supported before (when the type was object), so it doesn't seem like a major issue. I may fix this in a follow-up PR if it's easy enough.

@JukkaL JukkaL merged commit b202552 into master Jun 17, 2024
18 checks passed
@JukkaL JukkaL deleted the mypyc-type-aliases branch June 17, 2024 11:03
Comment on lines +3768 to +3770
if python_3_12_type_alias:
with self.allow_unbound_tvars_set():
rvalue.accept(self)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been fixed by #17404. Can you try it out?

@cdce8p
Copy link
Collaborator

cdce8p commented Jun 21, 2024

This should have been fixed by #17404. Can you try it out?

Yeah it is. Deleted my earlier comment, before I saw yours. Sorry for the noice.

--
Just for posterity. The example was type Alias = type[int]. With a The type "type[type]" is not generic and not indexable [misc] error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants