-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] support PEP 613 type aliases #20107
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
base: main
Are you sure you want to change the base?
Conversation
Diagnostic diff on typing conformance testsChanges were detected when running ty on typing conformance tests--- old-output.txt 2025-10-16 12:51:07.719997664 +0000
+++ new-output.txt 2025-10-16 12:51:11.082995592 +0000
@@ -1,27 +1,34 @@
-fatal[panic] Panicked at /home/runner/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/ef9f932/src/function/execute.rs:402:17 when checking `/home/runner/work/ruff/ruff/typing/conformance/tests/aliases_type_statement.py`: `PEP695TypeAliasType < 'db >::value_type_(Id(d417)): execute: too many cycle iterations`
-fatal[panic] Panicked at /home/runner/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/ef9f932/src/function/execute.rs:402:17 when checking `/home/runner/work/ruff/ruff/typing/conformance/tests/aliases_typealiastype.py`: `infer_definition_types(Id(16c43)): execute: too many cycle iterations`
+fatal[panic] Panicked at /home/runner/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/ef9f932/src/function/execute.rs:402:17 when checking `/home/runner/work/ruff/ruff/typing/conformance/tests/aliases_type_statement.py`: `PEP695TypeAlias < 'db >::value_type_(Id(d817)): execute: too many cycle iterations`
+fatal[panic] Panicked at /home/runner/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/ef9f932/src/function/execute.rs:402:17 when checking `/home/runner/work/ruff/ruff/typing/conformance/tests/aliases_typealiastype.py`: `infer_definition_types(Id(17043)): execute: too many cycle iterations`
_directives_deprecated_library.py:15:31: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `int`
_directives_deprecated_library.py:30:26: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `str`
_directives_deprecated_library.py:36:41: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `Self@__add__`
_directives_deprecated_library.py:41:25: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `int | float`
_directives_deprecated_library.py:45:24: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `str`
aliases_explicit.py:41:24: error[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[str, str]`?
-aliases_explicit.py:45:10: error[invalid-type-form] Variable of type `Literal["int | str"]` is not allowed in a type expression
-aliases_explicit.py:49:5: error[type-assertion-failure] Argument does not have asserted type `int | str`
-aliases_explicit.py:50:5: error[type-assertion-failure] Argument does not have asserted type `int | None`
-aliases_explicit.py:51:5: error[type-assertion-failure] Argument does not have asserted type `list[int | None]`
aliases_explicit.py:52:5: error[type-assertion-failure] Argument does not have asserted type `list[int]`
aliases_explicit.py:53:5: error[type-assertion-failure] Argument does not have asserted type `tuple[str, ...] | list[str]`
aliases_explicit.py:54:5: error[type-assertion-failure] Argument does not have asserted type `tuple[int, int, int, str]`
-aliases_explicit.py:55:5: error[type-assertion-failure] Argument does not have asserted type `(...) -> int`
aliases_explicit.py:56:5: error[type-assertion-failure] Argument does not have asserted type `(int, str, /) -> str`
aliases_explicit.py:57:5: error[type-assertion-failure] Argument does not have asserted type `(int, str, str, /) -> None`
aliases_explicit.py:59:5: error[type-assertion-failure] Argument does not have asserted type `int | str | None | list[list[int]]`
-aliases_explicit.py:60:5: error[type-assertion-failure] Argument does not have asserted type `(...) -> None`
-aliases_explicit.py:61:5: error[type-assertion-failure] Argument does not have asserted type `int | str`
-aliases_explicit.py:63:5: error[type-assertion-failure] Argument does not have asserted type `Literal[3, 4, 5] | None`
+aliases_explicit.py:79:21: error[invalid-type-form] Function calls are not allowed in type expressions
+aliases_explicit.py:80:21: error[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
+aliases_explicit.py:81:21: error[invalid-type-form] Tuple literals are not allowed in this context in a type expression
+aliases_explicit.py:81:22: error[invalid-type-form] Tuple literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
+aliases_explicit.py:82:21: error[invalid-type-form] List comprehensions are not allowed in type expressions
+aliases_explicit.py:83:21: error[invalid-type-form] Dict literals are not allowed in type expressions
+aliases_explicit.py:84:21: error[invalid-type-form] Function calls are not allowed in type expressions
+aliases_explicit.py:85:27: error[invalid-type-form] Int literals are not allowed in this context in a type expression
+aliases_explicit.py:86:21: error[invalid-type-form] `if` expressions are not allowed in type expressions
+aliases_explicit.py:87:21: error[invalid-type-form] Variable of type `Literal[3]` is not allowed in a type expression
+aliases_explicit.py:88:22: error[invalid-type-form] Boolean literals are not allowed in this context in a type expression
+aliases_explicit.py:89:22: error[invalid-type-form] Int literals are not allowed in this context in a type expression
+aliases_explicit.py:90:22: error[invalid-type-form] Boolean operations are not allowed in type expressions
+aliases_explicit.py:91:22: error[invalid-type-form] F-strings are not allowed in type expressions
+aliases_explicit.py:97:17: error[call-non-callable] Object of type `object` is not callable
aliases_explicit.py:98:1: error[type-assertion-failure] Argument does not have asserted type `list[str]`
-aliases_explicit.py:101:6: error[call-non-callable] Object of type `UnionType` is not callable
+aliases_explicit.py:101:6: error[call-non-callable] Object of type `object` is not callable
aliases_implicit.py:54:24: error[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[str, str]`?
aliases_implicit.py:60:5: error[type-assertion-failure] Argument does not have asserted type `int | str`
aliases_implicit.py:61:5: error[type-assertion-failure] Argument does not have asserted type `int | None`
@@ -48,10 +55,11 @@
aliases_implicit.py:133:6: error[call-non-callable] Object of type `UnionType` is not callable
aliases_newtype.py:15:1: error[type-assertion-failure] Argument does not have asserted type `int`
aliases_newtype.py:18:1: error[invalid-assignment] Object of type `NewType` is not assignable to `type`
+aliases_newtype.py:23:16: error[invalid-argument-type] Argument to function `isinstance` is incorrect: Expected `type | UnionType | tuple[Unknown, ...]`, found `NewType`
aliases_newtype.py:26:21: error[invalid-base] Invalid class base with type `NewType`
aliases_newtype.py:63:43: error[too-many-positional-arguments] Too many positional arguments to bound method `__init__`: expected 3, got 4
-aliases_variance.py:18:24: error[non-subscriptable] Cannot subscript object of type `<class 'ClassA[typing.TypeVar]'>` with no `__class_getitem__` method
-aliases_variance.py:28:16: error[non-subscriptable] Cannot subscript object of type `<class 'ClassA[typing.TypeVar]'>` with no `__class_getitem__` method
+aliases_variance.py:28:16: error[non-subscriptable] Cannot subscript object of type `A_Alias_1` with no `__getitem__` method
+aliases_variance.py:32:16: error[non-subscriptable] Cannot subscript object of type `A_Alias_2` with no `__getitem__` method
aliases_variance.py:44:16: error[non-subscriptable] Cannot subscript object of type `<class 'ClassB[typing.TypeVar, typing.TypeVar]'>` with no `__class_getitem__` method
annotations_forward_refs.py:49:10: error[invalid-type-form] Variable of type `Literal[1]` is not allowed in a type expression
annotations_forward_refs.py:54:11: error[fstring-type-annotation] Type expressions cannot use f-strings
@@ -166,6 +174,7 @@
classes_classvar.py:71:18: error[invalid-type-form] `ClassVar` annotations are not allowed for non-name targets
classes_classvar.py:73:26: error[invalid-type-form] `ClassVar` is not allowed in function return type annotations
classes_classvar.py:77:8: error[invalid-type-form] `ClassVar` annotations are only allowed in class-body scopes
+classes_classvar.py:78:20: error[invalid-type-form] Type qualifier `typing.ClassVar` is not allowed in type expressions (only in annotation expressions)
classes_classvar.py:111:1: error[invalid-attribute-access] Cannot assign to ClassVar `stats` from an instance of type `Starship`
classes_classvar.py:140:1: error[invalid-assignment] Object of type `ProtoAImpl` is not assignable to `ProtoA`
constructors_call_init.py:21:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `int`, found `float`
@@ -399,7 +408,7 @@
generics_defaults_referential.py:95:1: error[type-assertion-failure] Argument does not have asserted type `@Todo(unsupported nested subscript in type[X])`
generics_defaults_specialization.py:26:5: error[type-assertion-failure] Argument does not have asserted type `SomethingWithNoDefaults[int, str]`
generics_defaults_specialization.py:27:5: error[type-assertion-failure] Argument does not have asserted type `SomethingWithNoDefaults[int, bool]`
-generics_defaults_specialization.py:30:1: error[non-subscriptable] Cannot subscript object of type `<class 'SomethingWithNoDefaults[int, typing.TypeVar]'>` with no `__class_getitem__` method
+generics_defaults_specialization.py:30:1: error[non-subscriptable] Cannot subscript object of type `MyAlias` with no `__getitem__` method
generics_defaults_specialization.py:45:1: error[type-assertion-failure] Argument does not have asserted type `@Todo(unsupported nested subscript in type[X])`
generics_paramspec_basic.py:27:38: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `int`
generics_paramspec_components.py:49:20: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `tuple[@Todo(Support for `typing.ParamSpec`), ...]`
@@ -799,7 +808,9 @@
qualifiers_annotated.py:53:18: error[invalid-type-form] Boolean operations are not allowed in type expressions
qualifiers_annotated.py:54:18: error[fstring-type-annotation] Type expressions cannot use f-strings
qualifiers_annotated.py:64:8: error[invalid-type-form] Special form `typing.Annotated` expected at least 2 arguments (one type and at least one metadata element)
+qualifiers_annotated.py:77:1: error[invalid-assignment] Object of type `SmallInt` is not assignable to `type[Any]`
qualifiers_annotated.py:91:1: error[call-non-callable] Object of type `typing.Annotated` is not callable
+qualifiers_annotated.py:93:1: error[call-non-callable] Object of type `object` is not callable
qualifiers_final_annotation.py:18:7: error[invalid-type-form] Type qualifier `typing.Final` expected exactly 1 argument, got 2
qualifiers_final_annotation.py:71:1: error[invalid-assignment] Reassignment of `Final` symbol `RATE` is not allowed: Symbol later reassigned here
qualifiers_final_annotation.py:81:1: error[invalid-assignment] Cannot assign to final attribute `DEFAULT_ID` on type `<class 'ClassB'>`
@@ -839,12 +850,7 @@
specialtypes_type.py:120:5: error[unresolved-attribute] Type `type` has no attribute `unknown`
specialtypes_type.py:127:5: error[type-assertion-failure] Argument does not have asserted type `ProUser`
specialtypes_type.py:137:5: error[type-assertion-failure] Argument does not have asserted type `type[Any]`
-specialtypes_type.py:138:5: error[type-assertion-failure] Argument does not have asserted type `type[Any]`
specialtypes_type.py:139:5: error[type-assertion-failure] Argument does not have asserted type `type[Any]`
-specialtypes_type.py:140:5: error[type-assertion-failure] Argument does not have asserted type `type[Any]`
-specialtypes_type.py:143:1: error[unresolved-attribute] Type `typing.Type` has no attribute `unknown`
-specialtypes_type.py:145:1: error[unresolved-attribute] Type `<class 'type'>` has no attribute `unknown`
-specialtypes_type.py:146:1: error[unresolved-attribute] Type `GenericAlias` has no attribute `unknown`
specialtypes_type.py:160:1: error[type-assertion-failure] Argument does not have asserted type `int`
specialtypes_type.py:161:1: error[type-assertion-failure] Argument does not have asserted type `int`
specialtypes_type.py:169:5: error[invalid-assignment] Object of type `type` is not assignable to `type[int]`
@@ -862,9 +868,7 @@
tuples_type_compat.py:106:13: error[type-assertion-failure] Argument does not have asserted type `tuple[str, str] | tuple[int, int]`
tuples_type_compat.py:111:13: error[type-assertion-failure] Argument does not have asserted type `tuple[int, str, int]`
tuples_type_compat.py:126:13: error[type-assertion-failure] Argument does not have asserted type `tuple[int | str, str]`
-tuples_type_compat.py:127:13: error[type-assertion-failure] Argument does not have asserted type `@Todo(Support for `typing.TypeAlias`)`
tuples_type_compat.py:129:13: error[type-assertion-failure] Argument does not have asserted type `tuple[int | str, int]`
-tuples_type_compat.py:130:13: error[type-assertion-failure] Argument does not have asserted type `@Todo(Support for `typing.TypeAlias`)`
tuples_type_compat.py:153:5: error[type-assertion-failure] Argument does not have asserted type `Sequence[Never]`
tuples_type_compat.py:157:1: error[invalid-assignment] Object of type `tuple[Literal[1], Literal[""], Literal[""]]` is not assignable to `tuple[int, str]`
tuples_type_compat.py:162:1: error[invalid-assignment] Object of type `tuple[Literal[1], Literal[1], Literal[""]]` is not assignable to `tuple[int, *tuple[str, ...]]`
@@ -898,5 +902,5 @@
typeddicts_usage.py:28:17: error[missing-typed-dict-key] Missing required key 'name' in TypedDict `Movie` constructor
typeddicts_usage.py:28:18: error[invalid-key] Invalid key access on TypedDict `Movie`: Unknown key "title"
typeddicts_usage.py:40:24: error[invalid-type-form] The special form `typing.TypedDict` is not allowed in type expressions. Did you mean to use a concrete TypedDict or `collections.abc.Mapping[str, object]` instead?
-Found 900 diagnostics
+Found 904 diagnostics
WARN A fatal error occurred while checking some files. Not all project files were analyzed. See the diagnostics list above for details. |
CodSpeed Performance ReportMerging #20107 will improve performances by 21.89%Comparing Summary
Benchmarks breakdown
Footnotes
|
9bfc92f to
fee3400
Compare
This comment was marked as outdated.
This comment was marked as outdated.
cf75ad7 to
e8558a6
Compare
|
3c8dd22 to
e2ea575
Compare
ddb8ca5 to
0cdd287
Compare
…lMeta` (#20488) ## Summary Fixes astral-sh/ty#1218. This bug doesn't currently cause us any real-world issues, because we don't yet understand the signatures typeshed gives us for `isinstance()` and `issubclass()` (typeshed's annotations there use PEP-613 type aliases). #20107 demonstrates that this will start causing us issues as soon as we add support for PEP-613 aliases, however, so it makes sense to fix it now. ## Test Plan Added mdtests
0cdd287 to
546c7e4
Compare
| // Make sure that the `Type` enum does not grow unexpectedly. | ||
| #[cfg(not(debug_assertions))] | ||
| #[cfg(target_pointer_width = "64")] | ||
| static_assertions::assert_eq_size!(Type, [u8; 16]); | ||
| static_assertions::assert_eq_size!(Type, [u8; 24]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why the old assertion no longer passes after rebasing this PR on main. (It seemed to pass on earlier versions of this PR, IIRC.) This PR adds new Type variants, but the wrapped data is all Salsa-interned, and (from local experimentation -- I tried adding some more static_assertions::assert_eq_size!() calls on various wrapped structs and ran cargo check -p ty_python_semantic --release) doesn't appear particularly large
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what changed but I remember that @ibraheemdev ran into this as well.
it seems that SubclassOfType is 16 bytes and so is KnownInstanceType. But KnownInstanceType was 12 bytes before.
|
| Project | Old Status | New Status | Old Return Code | New Return Code |
|---|---|---|---|---|
hydra-zen |
success | abnormal exit | 1 |
101 |
Diagnostic changes:
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
1,300 | 107 | 177 |
type-assertion-failure |
185 | 256 | 32 |
call-non-callable |
389 | 0 | 0 |
no-matching-overload |
296 | 10 | 0 |
possibly-missing-attribute |
221 | 12 | 63 |
unused-ignore-comment |
17 | 246 | 0 |
non-subscriptable |
212 | 38 | 8 |
unsupported-operator |
60 | 137 | 7 |
unresolved-attribute |
61 | 90 | 52 |
invalid-assignment |
67 | 29 | 20 |
invalid-return-type |
26 | 38 | 25 |
invalid-type-form |
12 | 51 | 1 |
not-iterable |
6 | 9 | 7 |
possibly-unresolved-reference |
0 | 19 | 0 |
invalid-base |
17 | 0 | 0 |
invalid-exception-caught |
16 | 0 | 0 |
invalid-parameter-default |
8 | 0 | 7 |
unknown-argument |
5 | 7 | 0 |
invalid-context-manager |
0 | 0 | 10 |
possibly-missing-implicit-call |
5 | 3 | 0 |
index-out-of-bounds |
2 | 1 | 3 |
parameter-already-assigned |
3 | 0 | 0 |
invalid-raise |
1 | 0 | 0 |
| Total | 2,909 | 1,053 | 412 |
|
|
||
| /// A single instance of a PEP 613 type alias (in other words, an arbitrary type form at | ||
| /// runtime.) | ||
| TypeAlias(TypeAliasType<'db>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeAliasType could be a salsa::Supertype
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried it locally, it doesn't help. Type is still 192 bits on a release build, not 128
|
hah, I got excited about the Codspeed speedup there for a minute before I remembered that that's the project that now panics in mypy_primer 🤣 |
|
Notes on the ecosystem diagnostics:
|
Summary
Add support for PEP 613 type aliases (defined by annotating with
typing.TypeAlias), including recursive ones.Test Plan
Added mdtests and updated existing tests.