-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] bidirectional type inference using function return type annotations #20528
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
…e of expressions in return statements
Diagnostic diff on typing conformance testsNo changes detected when running ty on typing conformance tests ✅ |
|
…ith `is_disjoint_from` (#20538) ## Summary I found this bug while working on #20528. The minimum reproducible code is: ```python from __future__ import annotations from typing import NamedTuple from ty_extensions import is_disjoint_from, static_assert class Path(NamedTuple): prev: Path | None key: str static_assert(not is_disjoint_from(Path, Path)) ``` A stack overflow occurs when a nominal instance type inherits from `NamedTuple` and is defined recursively. This PR fixes this bug. ## Test Plan mdtest updated
d899f83
to
2d882b3
Compare
|
Lint rule | Added | Removed | Changed |
---|---|---|---|
invalid-argument-type |
12 | 15 | 16 |
invalid-return-type |
4 | 11 | 26 |
missing-typed-dict-key |
11 | 0 | 0 |
invalid-key |
3 | 0 | 0 |
no-matching-overload |
3 | 0 | 0 |
possibly-missing-attribute |
1 | 0 | 0 |
unused-ignore-comment |
1 | 0 | 0 |
Total | 35 | 26 | 42 |
2d882b3
to
ef75f0a
Compare
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 looks pretty good to me! Some small comments below. @dcreager and/or @ibraheemdev will probably be better reviewers, though; I haven't done much work on our bidirectional inference yet
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-Authored-By: Ibraheem Ahmed <ibraheem@ibraheem.ca>
87be495
to
1b6a505
Compare
Co-authored-by: Ibraheem Ahmed <ibraheem@ibraheem.ca>
25c8ffc
to
0249ba2
Compare
…iteral::raw_signature`
CodSpeed Performance ReportMerging #20528 will not alter performanceComparing Summary
Footnotes
|
…verloadLiteral::raw_signature`" This reverts commit 9507d72.
def _(x: int | None): | ||
# TODO: should be `int` | ||
reveal_type(union_param(x)) # 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.
Is this a regression?
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 is revealed as int | None
in main. The change is due to the addition of a branch that does nothing when matching in SpecializationBuilder::infer
.
As already mentioned, specialization between unions requires special handling, and falling back to the (Type::Union(_), _) => ...
branch could result in incorrect specialization. The default mapping T = Unknown
is suboptimal but not incorrect, and the mapping T = int | None
is also suboptimal, so I'm not sure whether this should be considered a regression.
Specialization between unions will be a future work.
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 is timely — I just added that same branch with an initial "better than nothing" heuristic in #20749.
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.
(Note that the heuristic in 20749 will not handle @mtshiba's example, since it only engages when formal
has precisely one top-level typevar, and actual
has none.)
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 think that's fine, this should be eventually fixed by @dcreager's constraint solver work, so I wouldn't worry too much about it.
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.
OK, I merged the latest changes and made a minor fix to prevent incorrect specialization.
I think I addressed all review comments. codspeed reports a slight performance regression, but for the same reason as #20635, I believe it is difficult to avoid this. The ecosystem reports are generally good, some false positive errors are due to TODOs in |
I think this might need minor updating now that I merged #20806 (since it should fix a test TODO added in that PR)? @ibraheemdev feel free to merge this if it looks ready to you. |
This looks great, thanks. |
Summary
Implements bidirectional type inference using function return type annotations.
This PR was originally proposed to solve astral-sh/ty#1167, but this does not fully resolve it on its own.
Additionally, I believe we need to allow dataclasses to generate their own
__new__
methods, use constructor return types for inference, and a mechanism to discard type narrowing like& ~AlwaysFalsy
if necessary (at a more general level than this PR).Test Plan
mdtest/bidirectional.md
is added.