[red-knot] Callable types are disjoint from literals (#17160)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run

## 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.
This commit is contained in:
Dhruv Manilawala 2025-04-03 03:38:13 +05:30 committed by GitHub
parent 28c68934a4
commit 177afabe18
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 0 deletions

View file

@ -379,3 +379,15 @@ static_assert(not is_disjoint_from(Callable[..., None], Callable[[Literal[1]], N
static_assert(not is_disjoint_from(Callable[[], Never], Callable[[], Never])) static_assert(not is_disjoint_from(Callable[[], Never], Callable[[], Never]))
static_assert(not is_disjoint_from(Callable[[Never], str], Callable[[Never], int])) static_assert(not is_disjoint_from(Callable[[Never], str], Callable[[Never], int]))
``` ```
A callable type is disjoint from all literal types.
```py
from knot_extensions import CallableTypeOf, is_disjoint_from, static_assert
from typing_extensions import Callable, Literal, Never
static_assert(is_disjoint_from(Callable[[], None], Literal[""]))
static_assert(is_disjoint_from(Callable[[], None], Literal[b""]))
static_assert(is_disjoint_from(Callable[[], None], Literal[1]))
static_assert(is_disjoint_from(Callable[[], None], Literal[True]))
```

View file

@ -1393,6 +1393,20 @@ impl<'db> Type<'db> {
false false
} }
(
Type::Callable(_),
Type::StringLiteral(_) | Type::BytesLiteral(_) | Type::SliceLiteral(_),
)
| (
Type::StringLiteral(_) | Type::BytesLiteral(_) | Type::SliceLiteral(_),
Type::Callable(_),
) => {
// 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.
true
}
(Type::Callable(_), _) | (_, Type::Callable(_)) => { (Type::Callable(_), _) | (_, Type::Callable(_)) => {
// TODO: Implement disjointness for general callable type with other types // TODO: Implement disjointness for general callable type with other types
false false