Skip to content

Commit 177afab

Browse files
authored
[red-knot] Callable types are disjoint from literals (#17160)
## Summary A callable type is disjoint from other literal types. For example, `Type::StringLiteral` must be an instance of exactly `str`, not a subclass of `str`, and `str` is not callable. The same applies to other literal types. This should hopefully fix #17144, I couldn't produce any failures after running property tests multiple times. ## Test Plan Add test cases for disjointness check between callable and other literal types. Run property tests multiple times.
1 parent 28c6893 commit 177afab

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,15 @@ static_assert(not is_disjoint_from(Callable[..., None], Callable[[Literal[1]], N
379379
static_assert(not is_disjoint_from(Callable[[], Never], Callable[[], Never]))
380380
static_assert(not is_disjoint_from(Callable[[Never], str], Callable[[Never], int]))
381381
```
382+
383+
A callable type is disjoint from all literal types.
384+
385+
```py
386+
from knot_extensions import CallableTypeOf, is_disjoint_from, static_assert
387+
from typing_extensions import Callable, Literal, Never
388+
389+
static_assert(is_disjoint_from(Callable[[], None], Literal[""]))
390+
static_assert(is_disjoint_from(Callable[[], None], Literal[b""]))
391+
static_assert(is_disjoint_from(Callable[[], None], Literal[1]))
392+
static_assert(is_disjoint_from(Callable[[], None], Literal[True]))
393+
```

crates/red_knot_python_semantic/src/types.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,20 @@ impl<'db> Type<'db> {
13931393
false
13941394
}
13951395

1396+
(
1397+
Type::Callable(_),
1398+
Type::StringLiteral(_) | Type::BytesLiteral(_) | Type::SliceLiteral(_),
1399+
)
1400+
| (
1401+
Type::StringLiteral(_) | Type::BytesLiteral(_) | Type::SliceLiteral(_),
1402+
Type::Callable(_),
1403+
) => {
1404+
// A callable type is disjoint from other literal types. For example,
1405+
// `Type::StringLiteral` must be an instance of exactly `str`, not a subclass
1406+
// of `str`, and `str` is not callable. The same applies to other literal types.
1407+
true
1408+
}
1409+
13961410
(Type::Callable(_), _) | (_, Type::Callable(_)) => {
13971411
// TODO: Implement disjointness for general callable type with other types
13981412
false

0 commit comments

Comments
 (0)