-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into dcreager/consolidate-any
* main: [red-knot] Move `UnionBuilder` tests to Markdown (#15374)
- Loading branch information
Showing
2 changed files
with
131 additions
and
97 deletions.
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
crates/red_knot_python_semantic/resources/mdtest/union_types.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# Union types | ||
|
||
This test suite covers certain basic properties and simplification strategies for union types. | ||
|
||
## Basic unions | ||
|
||
```py | ||
from typing import Literal | ||
|
||
def _(u1: int | str, u2: Literal[0] | Literal[1]) -> None: | ||
reveal_type(u1) # revealed: int | str | ||
reveal_type(u2) # revealed: Literal[0, 1] | ||
``` | ||
|
||
## Duplicate elements are collapsed | ||
|
||
```py | ||
def _(u1: int | int | str, u2: int | str | int) -> None: | ||
reveal_type(u1) # revealed: int | str | ||
reveal_type(u2) # revealed: int | str | ||
``` | ||
|
||
## `Never` is removed | ||
|
||
`Never` is an empty set, a type with no inhabitants. Its presence in a union is always redundant, | ||
and so we eagerly simplify it away. `NoReturn` is equivalent to `Never`. | ||
|
||
```py | ||
from typing_extensions import Never, NoReturn | ||
|
||
def never(u1: int | Never, u2: int | Never | str) -> None: | ||
reveal_type(u1) # revealed: int | ||
reveal_type(u2) # revealed: int | str | ||
|
||
def noreturn(u1: int | NoReturn, u2: int | NoReturn | str) -> None: | ||
reveal_type(u1) # revealed: int | ||
reveal_type(u2) # revealed: int | str | ||
``` | ||
|
||
## Flattening of nested unions | ||
|
||
```py | ||
from typing import Literal | ||
|
||
def _( | ||
u1: (int | str) | bytes, | ||
u2: int | (str | bytes), | ||
u3: int | (str | (bytes | complex)), | ||
) -> None: | ||
reveal_type(u1) # revealed: int | str | bytes | ||
reveal_type(u2) # revealed: int | str | bytes | ||
reveal_type(u3) # revealed: int | str | bytes | complex | ||
``` | ||
|
||
## Simplification using subtyping | ||
|
||
The type `S | T` can be simplified to `T` if `S` is a subtype of `T`: | ||
|
||
```py | ||
from typing_extensions import Literal, LiteralString | ||
|
||
def _( | ||
u1: str | LiteralString, u2: LiteralString | str, u3: Literal["a"] | str | LiteralString, u4: str | bytes | LiteralString | ||
) -> None: | ||
reveal_type(u1) # revealed: str | ||
reveal_type(u2) # revealed: str | ||
reveal_type(u3) # revealed: str | ||
reveal_type(u4) # revealed: str | bytes | ||
``` | ||
|
||
## Boolean literals | ||
|
||
The union `Literal[True] | Literal[False]` is exactly equivalent to `bool`: | ||
|
||
```py | ||
from typing import Literal | ||
|
||
def _( | ||
u1: Literal[True, False], | ||
u2: bool | Literal[True], | ||
u3: Literal[True] | bool, | ||
u4: Literal[True] | Literal[True, 17], | ||
u5: Literal[True, False, True, 17], | ||
) -> None: | ||
reveal_type(u1) # revealed: bool | ||
reveal_type(u2) # revealed: bool | ||
reveal_type(u3) # revealed: bool | ||
reveal_type(u4) # revealed: Literal[True, 17] | ||
reveal_type(u5) # revealed: bool | Literal[17] | ||
``` | ||
|
||
## Do not erase `Unknown` | ||
|
||
```py | ||
from knot_extensions import Unknown | ||
|
||
def _(u1: Unknown | str, u2: str | Unknown) -> None: | ||
reveal_type(u1) # revealed: Unknown | str | ||
reveal_type(u2) # revealed: str | Unknown | ||
``` | ||
|
||
## Collapse multiple `Unknown`s | ||
|
||
Since `Unknown` is a gradual type, it is not a subtype of anything, but multiple `Unknown`s in a | ||
union are still redundant: | ||
|
||
```py | ||
from knot_extensions import Unknown | ||
|
||
def _(u1: Unknown | Unknown | str, u2: Unknown | str | Unknown, u3: str | Unknown | Unknown) -> None: | ||
reveal_type(u1) # revealed: Unknown | str | ||
reveal_type(u2) # revealed: Unknown | str | ||
reveal_type(u3) # revealed: str | Unknown | ||
``` | ||
|
||
## Subsume multiple elements | ||
|
||
Simplifications still apply when `Unknown` is present. | ||
|
||
```py | ||
from knot_extensions import Unknown | ||
|
||
def _(u1: str | Unknown | int | object): | ||
reveal_type(u1) # revealed: Unknown | object | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters