[ty] more detailed description of "Size limit on unions of literals" in mdtest (#21804)

This commit is contained in:
Shunsuke Shibayama 2025-12-06 02:34:39 +09:00 committed by GitHub
parent b623189560
commit 2f05ffa2c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 37 additions and 3 deletions

View File

@ -229,9 +229,8 @@ def _(literals_2: Literal[0, 1], b: bool, flag: bool):
literals_128 = 2 * literals_64 + literals_2 # Literal[0, 1, .., 127] literals_128 = 2 * literals_64 + literals_2 # Literal[0, 1, .., 127]
literals_256 = 2 * literals_128 + literals_2 # Literal[0, 1, .., 255] literals_256 = 2 * literals_128 + literals_2 # Literal[0, 1, .., 255]
# Going beyond the MAX_UNION_LITERALS limit (currently 512): # Going beyond the MAX_NON_RECURSIVE_UNION_LITERALS limit (currently 256):
literals_512 = 2 * literals_256 + literals_2 # Literal[0, 1, .., 511] reveal_type(literals_256 if flag else 256) # revealed: int
reveal_type(literals_512 if flag else 512) # revealed: int
# Going beyond the limit when another type is already part of the union # Going beyond the limit when another type is already part of the union
bool_and_literals_128 = b if flag else literals_128 # bool | Literal[0, 1, ..., 127] bool_and_literals_128 = b if flag else literals_128 # bool | Literal[0, 1, ..., 127]
@ -245,6 +244,41 @@ def _(literals_2: Literal[0, 1], b: bool, flag: bool):
reveal_type(two if flag else literals_256_shifted) # revealed: int reveal_type(two if flag else literals_256_shifted) # revealed: int
``` ```
Recursively defined literal union types are widened earlier than non-recursively defined types for
faster convergence.
```py
class RecursiveAttr:
def __init__(self):
self.i = 0
def update(self):
self.i = self.i + 1
reveal_type(RecursiveAttr().i) # revealed: Unknown | int
# Here are some recursive but saturating examples. Because it's difficult to statically determine whether literal unions saturate or diverge,
# we widen them early, even though they may actually be convergent.
class RecursiveAttr2:
def __init__(self):
self.i = 0
def update(self):
self.i = (self.i + 1) % 9
reveal_type(RecursiveAttr2().i) # revealed: Unknown | Literal[0, 1, 2, 3, 4, 5, 6, 7, 8]
class RecursiveAttr3:
def __init__(self):
self.i = 0
def update(self):
self.i = (self.i + 1) % 10
# Going beyond the MAX_RECURSIVE_UNION_LITERALS limit:
reveal_type(RecursiveAttr3().i) # revealed: Unknown | int
```
## Simplifying gradually-equivalent types ## Simplifying gradually-equivalent types
If two types are gradually equivalent, we can keep just one of them in a union: If two types are gradually equivalent, we can keep just one of them in a union: