Skip to content

Commit 23382f5

Browse files
mtshibacarljm
andauthored
[red-knot] add test cases result in false positive errors (#16856)
## Summary From #16641 The previous PR attempted to fix the errors presented in this PR, but as discussed in the conversation, it was concluded that the approach was undesirable and that further work would be needed to fix the errors with a correct general solution. In this PR, I instead add the test cases from the previous PR as TODOs, as a starting point for future work. ## Test Plan --------- Co-authored-by: Carl Meyer <[email protected]>
1 parent c1971fd commit 23382f5

File tree

5 files changed

+90
-7
lines changed

5 files changed

+90
-7
lines changed

crates/red_knot_python_semantic/resources/mdtest/intersection_types.md

+14
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,7 @@ to the fact that `bool` is a `@final` class at runtime that cannot be subclassed
663663

664664
```py
665665
from knot_extensions import Intersection, Not, AlwaysTruthy, AlwaysFalsy
666+
from typing_extensions import Literal
666667

667668
class P: ...
668669

@@ -686,6 +687,19 @@ def f(
686687
reveal_type(f) # revealed: Never
687688
reveal_type(g) # revealed: Never
688689
reveal_type(h) # revealed: Never
690+
691+
def never(
692+
a: Intersection[Intersection[AlwaysFalsy, Not[Literal[False]]], bool],
693+
b: Intersection[Intersection[AlwaysTruthy, Not[Literal[True]]], bool],
694+
c: Intersection[Intersection[Literal[True], Not[AlwaysTruthy]], bool],
695+
d: Intersection[Intersection[Literal[False], Not[AlwaysFalsy]], bool],
696+
):
697+
# TODO: This should be `Never`
698+
reveal_type(a) # revealed: Literal[True]
699+
# TODO: This should be `Never`
700+
reveal_type(b) # revealed: Literal[False]
701+
reveal_type(c) # revealed: Never
702+
reveal_type(d) # revealed: Never
689703
```
690704

691705
## Simplification of `LiteralString`, `AlwaysTruthy` and `AlwaysFalsy`

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

+26-4
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ static_assert(not is_assignable_to(tuple[Any, Literal[2]], tuple[int, str]))
206206
## Union types
207207

208208
```py
209-
from knot_extensions import static_assert, is_assignable_to, Unknown
210-
from typing import Literal, Any
209+
from knot_extensions import AlwaysTruthy, AlwaysFalsy, static_assert, is_assignable_to, Unknown
210+
from typing_extensions import Literal, Any, LiteralString
211211

212212
static_assert(is_assignable_to(int, int | str))
213213
static_assert(is_assignable_to(str, int | str))
@@ -227,13 +227,22 @@ static_assert(not is_assignable_to(int | None, str | None))
227227
static_assert(not is_assignable_to(Literal[1] | None, int))
228228
static_assert(not is_assignable_to(Literal[1] | None, str | None))
229229
static_assert(not is_assignable_to(Any | int | str, int))
230+
231+
# TODO: No errors
232+
# error: [static-assert-error]
233+
static_assert(is_assignable_to(bool, Literal[False] | AlwaysTruthy))
234+
# error: [static-assert-error]
235+
static_assert(is_assignable_to(bool, Literal[True] | AlwaysFalsy))
236+
# error: [static-assert-error]
237+
static_assert(is_assignable_to(LiteralString, Literal[""] | AlwaysTruthy))
238+
static_assert(not is_assignable_to(Literal[True] | AlwaysFalsy, Literal[False] | AlwaysTruthy))
230239
```
231240

232241
## Intersection types
233242

234243
```py
235-
from knot_extensions import static_assert, is_assignable_to, Intersection, Not
236-
from typing_extensions import Any, Literal
244+
from knot_extensions import static_assert, is_assignable_to, Intersection, Not, AlwaysTruthy, AlwaysFalsy
245+
from typing_extensions import Any, Literal, final, LiteralString
237246

238247
class Parent: ...
239248
class Child1(Parent): ...
@@ -296,6 +305,19 @@ static_assert(is_assignable_to(Intersection[Any, Unrelated], Intersection[Any, P
296305
static_assert(is_assignable_to(Intersection[Any, Parent, Unrelated], Intersection[Any, Parent, Unrelated]))
297306
static_assert(is_assignable_to(Intersection[Unrelated, Any], Intersection[Unrelated, Not[Any]]))
298307
static_assert(is_assignable_to(Intersection[Literal[1], Any], Intersection[Unrelated, Not[Any]]))
308+
309+
# TODO: No errors
310+
# The condition `is_assignable_to(T & U, U)` should still be satisfied after the following transformations:
311+
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
312+
# error: [static-assert-error]
313+
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[""]]], AlwaysTruthy))
314+
# error: [static-assert-error]
315+
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal["", "a"]]], AlwaysTruthy))
316+
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
317+
# error: [static-assert-error]
318+
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[""]]], Not[AlwaysFalsy]))
319+
# error: [static-assert-error]
320+
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal["", "a"]]], Not[AlwaysFalsy]))
299321
```
300322

301323
## General properties

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

+20-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ static_assert(is_disjoint_from(None, Intersection[int, Not[str]]))
196196

197197
```py
198198
from typing_extensions import Literal, LiteralString
199-
from knot_extensions import TypeOf, is_disjoint_from, static_assert
199+
from knot_extensions import Intersection, Not, TypeOf, is_disjoint_from, static_assert, AlwaysFalsy, AlwaysTruthy
200200

201201
static_assert(is_disjoint_from(Literal[True], Literal[False]))
202202
static_assert(is_disjoint_from(Literal[True], Literal[1]))
@@ -223,6 +223,25 @@ static_assert(not is_disjoint_from(Literal[1], Literal[1]))
223223
static_assert(not is_disjoint_from(Literal["a"], Literal["a"]))
224224
static_assert(not is_disjoint_from(Literal["a"], LiteralString))
225225
static_assert(not is_disjoint_from(Literal["a"], str))
226+
227+
# TODO: No errors
228+
# error: [static-assert-error]
229+
static_assert(is_disjoint_from(AlwaysFalsy, Intersection[LiteralString, Not[Literal[""]]]))
230+
# error: [static-assert-error]
231+
static_assert(is_disjoint_from(Intersection[Not[Literal[True]], Not[Literal[False]]], bool))
232+
# error: [static-assert-error]
233+
static_assert(is_disjoint_from(Intersection[AlwaysFalsy, Not[Literal[False]]], bool))
234+
# error: [static-assert-error]
235+
static_assert(is_disjoint_from(Intersection[AlwaysTruthy, Not[Literal[True]]], bool))
236+
237+
# TODO: No errors
238+
# The condition `is_disjoint(T, Not[T])` must still be satisfied after the following transformations:
239+
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
240+
# error: [static-assert-error]
241+
static_assert(is_disjoint_from(Intersection[LiteralString, AlwaysTruthy], Not[LiteralString] | AlwaysFalsy))
242+
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
243+
# error: [static-assert-error]
244+
static_assert(is_disjoint_from(Intersection[LiteralString, Not[AlwaysFalsy]], Not[LiteralString] | AlwaysFalsy))
226245
```
227246

228247
### Class, module and function literals

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

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ static_assert(is_gradual_equivalent_to(Intersection[str | int, Not[type[Any]]],
4646

4747
static_assert(not is_gradual_equivalent_to(str | int, int | str | bytes))
4848
static_assert(not is_gradual_equivalent_to(str | int | bytes, int | str | dict))
49+
50+
# TODO: No errors
51+
# error: [static-assert-error]
52+
static_assert(is_gradual_equivalent_to(Unknown, Unknown | Any))
53+
# error: [static-assert-error]
54+
static_assert(is_gradual_equivalent_to(Unknown, Intersection[Unknown, Any]))
4955
```
5056

5157
## Tuples

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

+24-2
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,8 @@ static_assert(is_subtype_of(Never, AlwaysFalsy))
276276
### `AlwaysTruthy` and `AlwaysFalsy`
277277

278278
```py
279-
from knot_extensions import AlwaysTruthy, AlwaysFalsy, is_subtype_of, static_assert
280-
from typing import Literal
279+
from knot_extensions import AlwaysTruthy, AlwaysFalsy, Intersection, Not, is_subtype_of, static_assert
280+
from typing_extensions import Literal, LiteralString
281281

282282
static_assert(is_subtype_of(Literal[1], AlwaysTruthy))
283283
static_assert(is_subtype_of(Literal[0], AlwaysFalsy))
@@ -290,6 +290,28 @@ static_assert(not is_subtype_of(Literal[0], AlwaysTruthy))
290290

291291
static_assert(not is_subtype_of(str, AlwaysTruthy))
292292
static_assert(not is_subtype_of(str, AlwaysFalsy))
293+
294+
# TODO: No errors
295+
# error: [static-assert-error]
296+
static_assert(is_subtype_of(bool, Literal[False] | AlwaysTruthy))
297+
# error: [static-assert-error]
298+
static_assert(is_subtype_of(bool, Literal[True] | AlwaysFalsy))
299+
# error: [static-assert-error]
300+
static_assert(is_subtype_of(LiteralString, Literal[""] | AlwaysTruthy))
301+
static_assert(not is_subtype_of(Literal[True] | AlwaysFalsy, Literal[False] | AlwaysTruthy))
302+
303+
# TODO: No errors
304+
# The condition `is_subtype_of(T & U, U)` must still be satisfied after the following transformations:
305+
# `LiteralString & AlwaysTruthy` -> `LiteralString & ~Literal[""]`
306+
# error: [static-assert-error]
307+
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal[""]]], AlwaysTruthy))
308+
# error: [static-assert-error]
309+
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal["", "a"]]], AlwaysTruthy))
310+
# `LiteralString & ~AlwaysFalsy` -> `LiteralString & ~Literal[""]`
311+
# error: [static-assert-error]
312+
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal[""]]], Not[AlwaysFalsy]))
313+
# error: [static-assert-error]
314+
static_assert(is_subtype_of(Intersection[LiteralString, Not[Literal["", "a"]]], Not[AlwaysFalsy]))
293315
```
294316

295317
### Module literals

0 commit comments

Comments
 (0)