diff --git a/crates/ty_python_semantic/resources/mdtest/call/union.md b/crates/ty_python_semantic/resources/mdtest/call/union.md index 8d722288e4..09943c0801 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/union.md +++ b/crates/ty_python_semantic/resources/mdtest/call/union.md @@ -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_256 = 2 * literals_128 + literals_2 # Literal[0, 1, .., 255] - # Going beyond the MAX_UNION_LITERALS limit (currently 512): - literals_512 = 2 * literals_256 + literals_2 # Literal[0, 1, .., 511] - reveal_type(literals_512 if flag else 512) # revealed: int + # Going beyond the MAX_NON_RECURSIVE_UNION_LITERALS limit (currently 256): + reveal_type(literals_256 if flag else 256) # revealed: int # 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] @@ -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 ``` +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 If two types are gradually equivalent, we can keep just one of them in a union: