-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] Use typing.Self
for the first parameter of instance methods
#20517
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
Conversation
Diagnostic diff on typing conformance testsChanges were detected when running ty on typing conformance tests--- old-output.txt 2025-09-29 18:52:45.668425107 +0000
+++ new-output.txt 2025-09-29 18:52:49.013452786 +0000
@@ -420,17 +420,12 @@
generics_self_basic.py:14:9: error[type-assertion-failure] Argument does not have asserted type `Self@set_scale`
generics_self_basic.py:20:16: error[invalid-return-type] Return type does not match returned value: expected `Self@method2`, found `Shape`
generics_self_basic.py:33:16: error[invalid-return-type] Return type does not match returned value: expected `Self@cls_method2`, found `Shape`
-generics_self_basic.py:51:1: error[type-assertion-failure] Argument does not have asserted type `Shape`
-generics_self_basic.py:52:1: error[type-assertion-failure] Argument does not have asserted type `Circle`
generics_self_basic.py:54:1: error[type-assertion-failure] Argument does not have asserted type `Shape`
generics_self_basic.py:55:1: error[type-assertion-failure] Argument does not have asserted type `Circle`
generics_self_basic.py:64:38: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `Self@set_value`
generics_self_basic.py:67:26: error[invalid-type-form] Special form `typing.Self` expected no type parameter
-generics_self_basic.py:74:5: error[type-assertion-failure] Argument does not have asserted type `Container[int]`
-generics_self_basic.py:75:5: error[type-assertion-failure] Argument does not have asserted type `Container[str]`
-generics_self_basic.py:83:5: error[type-assertion-failure] Argument does not have asserted type `Container[T@object_with_generic_type]`
-generics_self_protocols.py:48:5: error[type-assertion-failure] Argument does not have asserted type `ShapeProtocol`
generics_self_protocols.py:61:19: error[invalid-argument-type] Argument to function `accepts_shape` is incorrect: Expected `ShapeProtocol`, found `BadReturnType`
+generics_self_usage.py:50:5: error[invalid-assignment] Object of type `def foo(self) -> int` is not assignable to `(typing.Self, /) -> int`
generics_self_usage.py:73:14: error[invalid-type-form] Variable of type `typing.Self` is not allowed in a type expression
generics_self_usage.py:73:23: error[invalid-type-form] Variable of type `typing.Self` is not allowed in a type expression
generics_self_usage.py:76:6: error[invalid-type-form] Variable of type `typing.Self` is not allowed in a type expression
@@ -860,5 +855,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 861 diagnostics
+Found 856 diagnostics
WARN A fatal error occurred while checking some files. Not all project files were analyzed. See the diagnostics list above for details. |
CodSpeed WallTime Performance ReportMerging #20517 will degrade performances by 14.5%Comparing Summary
Benchmarks breakdown
|
CodSpeed Instrumentation Performance ReportMerging #20517 will degrade performances by 9.78%Comparing Summary
Benchmarks breakdown
|
This comment was marked as off-topic.
This comment was marked as off-topic.
|
|
Lint rule | Added | Removed | Changed |
---|---|---|---|
type-assertion-failure |
15 | 567 | 0 |
invalid-argument-type |
546 | 0 | 14 |
unsupported-operator |
170 | 0 | 8 |
unresolved-attribute |
96 | 0 | 0 |
unused-ignore-comment |
0 | 71 | 0 |
possibly-missing-attribute |
58 | 0 | 12 |
invalid-assignment |
33 | 0 | 6 |
non-subscriptable |
32 | 0 | 0 |
invalid-return-type |
19 | 4 | 7 |
no-matching-overload |
30 | 0 | 0 |
not-iterable |
9 | 0 | 0 |
call-non-callable |
5 | 2 | 0 |
division-by-zero |
0 | 3 | 0 |
invalid-key |
2 | 0 | 0 |
possibly-missing-implicit-call |
0 | 0 | 2 |
too-many-positional-arguments |
2 | 0 | 0 |
invalid-context-manager |
1 | 0 | 0 |
invalid-type-form |
1 | 0 | 0 |
parameter-already-assigned |
1 | 0 | 0 |
redundant-cast |
1 | 0 | 0 |
unknown-argument |
1 | 0 | 0 |
Total | 1,022 | 647 | 49 |
92e01d5
to
433ec04
Compare
reveal_type(x) # revealed: list[A | str] | ||
for item in x: | ||
reveal_type(item) # revealed: list[A | str] | str | ||
reveal_type(item) # revealed: list[Any | str] | str |
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.
This regression is tracked in astral-sh/ty#1157
771fef0
to
e54903f
Compare
1254b5f
to
b494fef
Compare
b494fef
to
1b44768
Compare
# TODO: this should be B | ||
reveal_type(B().a_property) # revealed: Unknown |
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.
This should also be fixed. I have not looked into it yet. Maybe it can be deferred to a follow-up.
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.
Thank you, this looks great. I haven't analysed the ecosystem report at all, but I trust your analysis if you say it looks good!
And thank you so much @Glyphack as well! |
Part of astral-sh/ty#159 This PR only adjusts the signature of a method so if it has a `self` argument then that argument will have type of `Typing.Self` even if it's not specified. If user provides an explicit annotation then Ty will not override that annotation. - astral-sh/ty#1131 - astral-sh/ty#1157 - astral-sh/ty#1156 - astral-sh/ty#1173 - #20328 - astral-sh/ty#1163 - astral-sh/ty#1196 Added mdtests. Also some tests need #18473 to work completely. So I added a todo for those new cases that I added. --------- Co-authored-by: David Peter <mail@david-peter.de>
2b3aec1
to
3ce98ce
Compare
The performance regressions look severe, but I am going to merge this. We can always work on performance later, and it's probably also important to keep in mind that across the whole ecosystem, this is more of a 3% slowdown. |
* main: (21 commits) [ty] Literal promotion refactor (#20646) [ty] Add tests for nested generic functions (#20631) [`cli`] Add conflict between `--add-noqa` and `--diff` options (#20642) [ty] Ensure first-party search paths always appear in a sensible order (#20629) [ty] Use `typing.Self` for the first parameter of instance methods (#20517) [ty] Remove unnecessary `parsed_module()` calls (#20630) Remove `TextEmitter` (#20595) [ty] Use fully qualified names to distinguish ambiguous protocols in diagnostics (#20627) [ty] Ecosystem analyzer: relax timeout thresholds (#20626) [ty] Apply type mappings to functions eagerly (#20596) [ty] Improve disambiguation of class names in diagnostics (#20603) Add the *The Basics* title back to CONTRIBUTING.md (#20624) [`playground`] Fix quick fixes for empty ranges in playground (#20599) Update dependency ruff to v0.13.2 (#20622) [`ruff`] Fix minor typos in doc comments (#20623) Update dependency PyYAML to v6.0.3 (#20621) Update cargo-bins/cargo-binstall action to v1.15.6 (#20620) Fixed documentation for try_consider_else (#20587) [ty] Use `Top` materializations for `TypeIs` special form (#20591) [ty] Simplify `Any | (Any & T)` to `Any` (#20593) ...
Summary
Modify the (external) signature of instance methods such that the first parameter uses
Self
unless it is explicitly annotated. This allows us to correctly type-check more code, and allows us to infer correct return types for many functions that returnSelf
. For example:part of astral-sh/ty#159
Co-authored by: @Glyphack
Performance
I ran benchmarks locally on
attrs
,freqtrade
andcolour
, the projects with the largest regressions on CodSpeed. I see much smaller effects locally, but can definitely reproduce the regression onattrs
. From looking at the profiling results (on Codspeed), it seems that we simply do more type inference work, which seems plausible, given that we now understand much more return types (of many stdlib functions). In particular, whenever a function uses an implicitself
and returnsSelf
(without mentioningSelf
anywhere else in its signature), we will now infer the correct type, whereas we would previously returnUnknown
. This also means that we need to invoke the generics solver in more cases. Comparing half a million lines of log output on attrs, I can see that we do 5% more "work" (number of lines in the log), and have a lot moreapply_specialization
events (7108 vs 4304). On freqtrade, I see similar numbers forapply_specialization
(11360 vs 5138 calls). Given these results, I'm not sure if it's generally worth doing more performance work, especially since none of the code modifications themselves seem to be likely candidates for regressions../ty_main check /home/shark/ecosystem/attrs
./ty_self check /home/shark/ecosystem/attrs
./ty_main check /home/shark/ecosystem/freqtrade
./ty_self check /home/shark/ecosystem/freqtrade
./ty_main check /home/shark/ecosystem/colour
./ty_self check /home/shark/ecosystem/colour
Test Plan
New Markdown tests
Ecosystem report
@staticmethod
?invalid-operator
false positives in matrix multiplication due to our limited understanding of genericCallable[[Callable[[T1, T2], T3]], Callable[[T1, T2], T3]]
"identity" types of decorators. This is not related to type-of-self.Typing conformance results
The changes are all correct, except for
+generics_self_usage.py:50:5: error[invalid-assignment] Object of type `def foo(self) -> int` is not assignable to `(typing.Self, /) -> int`
which is related to an assignability problem involving type variables on both sides: