-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] Clarify behavior of constraint sets for gradual upper bounds and constraints #21287
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 testsNo changes detected when running ty on typing conformance tests ✅ |
|
| must satisfy the constraint set. (That means we will almost always choose `Never` — or more | ||
| precisely, the bottom specialization — as the upper bound.) In inferable positions, the opposite is |
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 only holds true if the upper bound of a typevar is a gradual specialization of an invariant type? The bottom materialization of list[Any] is Never, but the bottom materialization of Sequence[Any] is Sequence[Never], since Sequence[Never] is a subtype of Sequence[int] and Sequence[str], and is still an inhabited type ([], () can both inhabit Sequence[Never], for example). Similarly for contravariance, the bottom materialization of Callable[[Any], int] is Callable[[object], int].
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.
Which part doesn't hold true? This might be poor wording on my part — I am not trying to claim that the bottom materialization is always Never. I am (attempting to) say that for T: Any, we pick T: Never, but it's more precise to say that we pick the bottom specialization, because for T: list[Any], we pick T: Bottom[list[Any]].
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.
might be poor wording on my part
I think I understood it the way you explained in your comment now, but I also stumbled over 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.
This might be poor wording on my part — I am not trying to claim that the bottom materialization is always
Never.
Ah, okay -- yes, I think the wording can be improved there a little!
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.
Reworded this, lmkwyt
When checking whether a constraint set is satisfied, if a typevar has a non-fully-static upper bound or constraint, we are free to choose any materialization that makes the check succeed.
In non-inferable positions, we have to show that the constraint set is satisfied for all valid specializations, so it's best to choose the most restrictive materialization, since that minimizes the set of valid specializations that have to pass.
In inferable positions, we only have to show that the constraint set is satisfied for some valid specializations, so it's best to choose the most permissive materialization, since that maximizes our chances of finding a specialization that passes.