mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-02 12:58:27 +00:00
[ty] Perform assignability etc checks using new Constraints trait (#19838)
"Why would you do this? This looks like you just replaced `bool` with an overly complex trait" Yes that's correct! This should be a no-op refactoring. It replaces all of the logic in our assignability, subtyping, equivalence, and disjointness methods to work over an arbitrary `Constraints` trait instead of only working on `bool`. The methods that `Constraints` provides looks very much like what we get from `bool`. But soon we will add a new impl of this trait, and some new methods, that let us express "fuzzy" constraints that aren't always true or false. (In particular, a constraint will express the upper and lower bounds of the allowed specializations of a typevar.) Even once we have that, most of the operations that we perform on constraint sets will be the usual boolean operations, just on sets. (`false` becomes empty/never; `true` becomes universe/always; `or` becomes union; `and` becomes intersection; `not` becomes negation.) So it's helpful to have this separate PR to refactor how we invoke those operations without introducing the new functionality yet. Note that we also have translations of `Option::is_some_and` and `is_none_or`, and of `Iterator::any` and `all`, and that the `and`, `or`, `when_any`, and `when_all` methods are meant to short-circuit, just like the corresponding boolean operations. For constraint sets, that depends on being able to implement the `is_always` and `is_never` trait methods. --------- Co-authored-by: Carl Meyer <carl@astral.sh> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
045cba382a
commit
14fe1228e7
13 changed files with 1148 additions and 602 deletions
|
|
@ -327,6 +327,17 @@ def union[T: Base, U: (Base, Unrelated)](t: T, u: U) -> None:
|
|||
static_assert(is_subtype_of(U, U | None))
|
||||
```
|
||||
|
||||
A bound or constrained typevar in a union with a dynamic type is assignable to the typevar:
|
||||
|
||||
```py
|
||||
def union_with_dynamic[T: Base, U: (Base, Unrelated)](t: T, u: U) -> None:
|
||||
static_assert(is_assignable_to(T | Any, T))
|
||||
static_assert(is_assignable_to(U | Any, U))
|
||||
|
||||
static_assert(not is_subtype_of(T | Any, T))
|
||||
static_assert(not is_subtype_of(U | Any, U))
|
||||
```
|
||||
|
||||
And an intersection of a typevar with another type is always a subtype of the TypeVar:
|
||||
|
||||
```py
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue