Skip to content

Commit a089eb9

Browse files
committed
fix is_subtype_of/is_assignable_to handling & organize test cases
1 parent 35a6140 commit a089eb9

File tree

6 files changed

+312
-149
lines changed

6 files changed

+312
-149
lines changed

crates/red_knot_python_semantic/resources/mdtest/type_properties/is_assignable_to.md

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -306,44 +306,25 @@ static_assert(is_assignable_to(Intersection[Unrelated, Not[int]], Not[int]))
306306
static_assert(is_assignable_to(Intersection[Intersection[str, Not[Literal[""]]], int], Intersection[str, Not[Literal[""]]]))
307307
static_assert(is_assignable_to(Intersection[Intersection[Any, Not[int]], Not[str]], Intersection[Any, Not[int]]))
308308

309+
# The condition `is_assignable_to(T & U, U)` should still be satisfied after the following transformations:
309310
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
310-
static_assert(is_assignable_to(Intersection[LiteralString, AlwaysTruthy], AlwaysTruthy))
311311
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[""]]], AlwaysTruthy))
312312
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal["", "a"]]], AlwaysTruthy))
313-
static_assert(not is_assignable_to(Intersection[object, Not[Literal[""]]], AlwaysTruthy))
314-
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[""]]], Intersection[AlwaysTruthy, Not[Literal[1]]]))
315-
# `LiteralString & ~AlwaysTruthy` -> `LiteralString & Literal[""]`
316-
static_assert(is_assignable_to(Intersection[LiteralString, Not[AlwaysTruthy]], Not[AlwaysTruthy]))
317-
static_assert(is_assignable_to(Intersection[LiteralString, Literal[""]], Not[AlwaysTruthy]))
318-
static_assert(not is_assignable_to(Intersection[LiteralString, Literal["", "a"]], Not[AlwaysTruthy]))
319-
static_assert(is_assignable_to(Intersection[LiteralString, Not[AlwaysTruthy]], Literal[""]))
320-
static_assert(is_assignable_to(Intersection[LiteralString, Literal[""]], Literal[""]))
321-
# `bool & ~AlwaysTruthy`, `bool & ~Literal[True]` -> `bool & Literal[False]`
322-
static_assert(is_assignable_to(Intersection[bool, Not[AlwaysTruthy]], Literal[False]))
323-
static_assert(is_assignable_to(Intersection[bool, Not[Literal[True]]], Literal[False]))
324-
325-
# `LiteralString & AlwaysFalsy` -> `LiteralString & Literal[""]`
326-
static_assert(is_assignable_to(Intersection[LiteralString, AlwaysFalsy], AlwaysFalsy))
327-
static_assert(is_assignable_to(Intersection[LiteralString, Literal[""]], AlwaysFalsy))
328-
static_assert(not is_assignable_to(Intersection[LiteralString, Literal["", "a"]], AlwaysFalsy))
329-
static_assert(is_assignable_to(Intersection[LiteralString, AlwaysFalsy], Literal[""]))
313+
# `LiteralString & ~AlwaysTruthy` -> `Literal[""]`
314+
static_assert(is_assignable_to(Literal[""], Not[AlwaysTruthy]))
315+
static_assert(not is_assignable_to(Literal["", "a"], Not[AlwaysTruthy]))
316+
# `LiteralString & AlwaysFalsy` -> `Literal[""]`
317+
static_assert(is_assignable_to(Literal[""], AlwaysFalsy))
318+
static_assert(not is_assignable_to(Literal["", "a"], AlwaysFalsy))
330319
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
331-
static_assert(is_assignable_to(Intersection[LiteralString, Not[AlwaysFalsy]], Not[AlwaysFalsy]))
332320
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[""]]], Not[AlwaysFalsy]))
333321
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal["", "a"]]], Not[AlwaysFalsy]))
334-
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `bool & Literal[True]`
335-
static_assert(is_assignable_to(Intersection[bool, Not[AlwaysFalsy]], Literal[True]))
336-
static_assert(is_assignable_to(Intersection[bool, Not[Literal[False]]], Literal[True]))
337-
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `bool & Literal[True]`
338-
static_assert(is_assignable_to(Intersection[bool, Not[AlwaysFalsy]], Literal[True]))
339-
static_assert(is_assignable_to(Intersection[bool, Not[Literal[False]]], Literal[True]))
340-
341-
static_assert(is_assignable_to(Intersection[bool, Literal[False] | AlwaysTruthy], Literal[False] | AlwaysTruthy))
342-
static_assert(
343-
is_assignable_to(
344-
Intersection[Intersection[AlwaysFalsy, Not[Literal[False]]], bool], Intersection[AlwaysFalsy, Not[Literal[False]]]
345-
)
346-
)
322+
# `bool & ~AlwaysTruthy`, `bool & ~Literal[True]` -> `Literal[False]`
323+
static_assert(is_assignable_to(Literal[False], Not[AlwaysTruthy]))
324+
static_assert(is_assignable_to(Literal[False], Not[Literal[True]]))
325+
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `Literal[True]`
326+
static_assert(is_assignable_to(Literal[True], Not[AlwaysFalsy]))
327+
static_assert(is_assignable_to(Literal[True], Not[Literal[False]]))
347328
```
348329

349330
## General properties

crates/red_knot_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static_assert(is_disjoint_from(None, Intersection[int, Not[str]]))
200200

201201
```py
202202
from typing_extensions import Literal, LiteralString
203-
from knot_extensions import Intersection, Not, TypeOf, is_disjoint_from, static_assert
203+
from knot_extensions import Intersection, Not, TypeOf, is_disjoint_from, static_assert, AlwaysFalsy, AlwaysTruthy
204204

205205
static_assert(is_disjoint_from(Literal[True], Literal[False]))
206206
static_assert(is_disjoint_from(Literal[True], Literal[1]))
@@ -231,6 +231,31 @@ static_assert(not is_disjoint_from(Literal["a"], str))
231231
static_assert(is_disjoint_from(Intersection[str, Not[Literal["a"]]], Literal["a"]))
232232
static_assert(is_disjoint_from(Intersection[str, Not[Literal["a", "b"]]], Literal["a"]))
233233
static_assert(not is_disjoint_from(Intersection[str, Not[Literal["a"]]], Literal["b"]))
234+
235+
static_assert(is_disjoint_from(AlwaysFalsy, Intersection[LiteralString, Not[Literal[""]]]))
236+
static_assert(is_disjoint_from(AlwaysTruthy, Literal[""]))
237+
238+
static_assert(is_disjoint_from(Intersection[Not[Literal[True]], Not[Literal[False]]], bool))
239+
static_assert(is_disjoint_from(Intersection[AlwaysFalsy, Not[Literal[False]]], bool))
240+
static_assert(is_disjoint_from(Intersection[AlwaysTruthy, Not[Literal[True]]], bool))
241+
static_assert(is_disjoint_from(Intersection[Literal[True], Not[AlwaysTruthy]], bool))
242+
static_assert(is_disjoint_from(Intersection[Literal[False], Not[AlwaysFalsy]], bool))
243+
244+
# The condition `is_disjoint(T, Not[T])` must still be satisfied after the following transformations:
245+
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
246+
static_assert(is_disjoint_from(Intersection[LiteralString, AlwaysTruthy], Not[LiteralString] | AlwaysFalsy))
247+
# `LiteralString & ~AlwaysTruthy` -> `LiteralString & Literal[""]`
248+
static_assert(is_disjoint_from(Intersection[LiteralString, Not[AlwaysTruthy]], Not[LiteralString] | AlwaysTruthy))
249+
# `bool & ~AlwaysTruthy`, `bool & ~Literal[True]` -> `bool & Literal[False]`
250+
static_assert(is_disjoint_from(Intersection[bool, Not[AlwaysTruthy]], Not[bool] | AlwaysTruthy))
251+
static_assert(is_disjoint_from(Intersection[bool, Not[Literal[True]]], Not[bool] | Literal[True]))
252+
# `LiteralString & AlwaysFalsy` -> `LiteralString & Literal[""]`
253+
static_assert(is_disjoint_from(Intersection[LiteralString, AlwaysFalsy], Not[LiteralString] | AlwaysTruthy))
254+
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
255+
static_assert(is_disjoint_from(Intersection[LiteralString, Not[AlwaysFalsy]], Not[LiteralString] | AlwaysFalsy))
256+
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `bool & Literal[True]`
257+
static_assert(is_disjoint_from(Intersection[bool, Not[AlwaysFalsy]], Not[bool] | AlwaysFalsy))
258+
static_assert(is_disjoint_from(Intersection[bool, Not[Literal[False]]], Not[bool] | Literal[False]))
234259
```
235260

236261
### Class, module and function literals

crates/red_knot_python_semantic/resources/mdtest/type_properties/is_equivalent_to.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,26 @@ class R: ...
118118
static_assert(is_equivalent_to(Intersection[tuple[P | Q], R], Intersection[tuple[Q | P], R]))
119119
```
120120

121+
## Transformation by intersection
122+
123+
```py
124+
from knot_extensions import Intersection, Not, AlwaysTruthy, AlwaysFalsy, static_assert, is_equivalent_to
125+
from typing_extensions import Literal, LiteralString
126+
127+
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
128+
static_assert(is_equivalent_to(Intersection[LiteralString, AlwaysTruthy], Intersection[LiteralString, Not[Literal[""]]]))
129+
# `LiteralString & ~AlwaysTruthy` -> `Literal[""]`
130+
static_assert(is_equivalent_to(Intersection[LiteralString, Not[AlwaysTruthy]], Literal[""]))
131+
# `LiteralString & AlwaysFalsy` -> `Literal[""]`
132+
static_assert(is_equivalent_to(Intersection[LiteralString, AlwaysFalsy], Literal[""]))
133+
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
134+
static_assert(is_equivalent_to(Intersection[LiteralString, Not[AlwaysFalsy]], Intersection[LiteralString, Not[Literal[""]]]))
135+
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `bool & Literal[True]`
136+
static_assert(is_equivalent_to(Intersection[bool, Not[AlwaysFalsy]], Literal[True]))
137+
static_assert(is_equivalent_to(Intersection[bool, Not[Literal[False]]], Literal[True]))
138+
# `bool & ~AlwaysTruthy`, `bool & ~Literal[True]` -> `bool & Literal[False]`
139+
static_assert(is_equivalent_to(Intersection[bool, Not[AlwaysTruthy]], Literal[False]))
140+
static_assert(is_equivalent_to(Intersection[bool, Not[Literal[True]]], Literal[False]))
141+
```
142+
121143
[the equivalence relation]: https://typing.readthedocs.io/en/latest/spec/glossary.html#term-equivalent

crates/red_knot_python_semantic/resources/mdtest/type_properties/is_subtype_of.md

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -297,36 +297,25 @@ static_assert(is_subtype_of(bool, Literal[True] | AlwaysFalsy))
297297
static_assert(not is_subtype_of(Literal[True] | AlwaysFalsy, Literal[False] | AlwaysTruthy))
298298
static_assert(is_subtype_of(LiteralString, Literal[""] | AlwaysTruthy))
299299

300+
# The condition `is_subtype_of(T & U, U)` must still be satisfied after the following transformations:
300301
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
301-
static_assert(is_subtype_of(Intersection[LiteralString, AlwaysTruthy], AlwaysTruthy))
302302
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal[""]]], AlwaysTruthy))
303303
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal["", "a"]]], AlwaysTruthy))
304-
static_assert(not is_subtype_of(Intersection[object, Not[Literal[""]]], AlwaysTruthy))
305-
# `LiteralString & ~AlwaysTruthy` -> `LiteralString & Literal[""]`
306-
static_assert(is_subtype_of(Intersection[LiteralString, Not[AlwaysTruthy]], Not[AlwaysTruthy]))
307-
static_assert(is_subtype_of(Intersection[LiteralString, Literal[""]], Not[AlwaysTruthy]))
308-
static_assert(not is_subtype_of(Intersection[LiteralString, Literal["", "a"]], Not[AlwaysTruthy]))
309-
static_assert(is_subtype_of(Intersection[LiteralString, Not[AlwaysTruthy]], Literal[""]))
310-
# `bool & ~AlwaysTruthy`, `bool & ~Literal[True]` -> `bool & Literal[False]`
311-
static_assert(is_subtype_of(Intersection[bool, Not[AlwaysTruthy]], Literal[False]))
312-
static_assert(is_subtype_of(Intersection[bool, Not[Literal[True]]], Literal[False]))
313-
314-
# `LiteralString & AlwaysFalsy` -> `LiteralString & Literal[""]`
315-
static_assert(is_subtype_of(Intersection[LiteralString, AlwaysFalsy], AlwaysFalsy))
316-
static_assert(is_subtype_of(Intersection[LiteralString, Literal[""]], AlwaysFalsy))
317-
static_assert(not is_subtype_of(Intersection[LiteralString, Literal["", "a"]], AlwaysFalsy))
318-
static_assert(is_subtype_of(Intersection[LiteralString, AlwaysFalsy], Literal[""]))
319-
static_assert(is_subtype_of(Intersection[LiteralString, Literal[""]], Literal[""]))
320-
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
321-
static_assert(is_subtype_of(Intersection[LiteralString, Not[AlwaysFalsy]], Not[AlwaysFalsy]))
304+
# `LiteralString & ~AlwaysTruthy` -> `Literal[""]`
305+
static_assert(is_subtype_of(Literal[""], Not[AlwaysTruthy]))
306+
static_assert(not is_subtype_of(Literal["", "a"], Not[AlwaysTruthy]))
307+
# `LiteralString & AlwaysFalsy` -> `Literal[""]`
308+
static_assert(is_subtype_of(Literal[""], AlwaysFalsy))
309+
static_assert(not is_subtype_of(Literal["", "a"], AlwaysFalsy))
310+
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
322311
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal[""]]], Not[AlwaysFalsy]))
323312
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal["", "a"]]], Not[AlwaysFalsy]))
324-
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `bool & Literal[True]`
325-
static_assert(is_subtype_of(Intersection[bool, Not[AlwaysFalsy]], Literal[True]))
326-
static_assert(is_subtype_of(Intersection[bool, Not[Literal[False]]], Literal[True]))
327-
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `bool & Literal[True]`
328-
static_assert(is_subtype_of(Intersection[bool, Not[AlwaysFalsy]], Literal[True]))
329-
static_assert(is_subtype_of(Intersection[bool, Not[Literal[False]]], Literal[True]))
313+
# `bool & ~AlwaysTruthy`, `bool & ~Literal[True]` -> `Literal[False]`
314+
static_assert(is_subtype_of(Literal[False], Not[AlwaysTruthy]))
315+
static_assert(is_subtype_of(Literal[False], Not[Literal[True]]))
316+
# `bool & ~AlwaysFalsy`, `bool & ~Literal[False]` -> `Literal[True]`
317+
static_assert(is_subtype_of(Literal[True], Not[AlwaysFalsy]))
318+
static_assert(is_subtype_of(Literal[True], Not[Literal[False]]))
330319
```
331320

332321
### Module literals

0 commit comments

Comments
 (0)