@@ -13,9 +13,6 @@ static_assert(is_single_valued(Literal[1]))
1313static_assert(is_single_valued(Literal[" abc" ]))
1414static_assert(is_single_valued(Literal[b " abc" ]))
1515
16- static_assert(is_single_valued(tuple[()]))
17- static_assert(is_single_valued(tuple[Literal[True ], Literal[1 ]]))
18-
1916static_assert(not is_single_valued(str ))
2017static_assert(not is_single_valued(Never))
2118static_assert(not is_single_valued(Any))
@@ -35,6 +32,43 @@ static_assert(is_single_valued(TypeOf[types.FunctionType.__get__]))
3532static_assert(is_single_valued(TypeOf[A.method.__get__ ]))
3633```
3734
35+ Tuple types are not single-valued, because the type ` tuple[int, str] ` means "any two-element
36+ instance of ` tuple ` where the first element is ` int ` and the second is ` str ` , * or* any instance of a
37+ subclass of ` tuple[int, str] ` ". It's easy to create a subclass of ` tuple[int, str] ` that is
38+ Liskov-compliant but not single-valued, which therefore means that ` tuple[int, str] ` cannot be
39+ single-valued, as it is a supertype of its subclass, so can only be single-valued if all its
40+ subtypes are single-valued:
41+
42+ ``` py
43+ from ty_extensions import is_single_valued, static_assert
44+
45+ class EmptyTupleSubclass (tuple[()]):
46+ def __eq__ (self , other : object ) -> bool :
47+ return isinstance (other, EmptyTupleSubclass) and len (other) == 0
48+
49+ static_assert(not is_single_valued(tuple[()]))
50+ static_assert(not is_single_valued(EmptyTupleSubclass))
51+
52+ class SingleElementTupleSubclass (tuple[int ]):
53+ def __eq__ (self , other : object ) -> bool :
54+ return isinstance (other, SingleElementTupleSubclass) and len (other) == 1 and isinstance (other[0 ], int )
55+
56+ static_assert(not is_single_valued(tuple[int ]))
57+ static_assert(not is_single_valued(SingleElementTupleSubclass))
58+
59+ class TwoElementTupleSubclass (tuple[str , bytes ]):
60+ def __eq__ (self , other : object ) -> bool :
61+ return (
62+ isinstance (other, TwoElementTupleSubclass)
63+ and len (other) == 2
64+ and isinstance (other[0 ], str )
65+ and isinstance (other[1 ], bytes )
66+ )
67+
68+ static_assert(not is_single_valued(tuple[str , bytes ]))
69+ static_assert(not is_single_valued(TwoElementTupleSubclass))
70+ ```
71+
3872An enum literal is only considered single-valued if it has no custom ` __eq__ ` /` __ne__ ` method, or if
3973these methods always return ` True ` /` False ` , respectively. Otherwise, the single member of the enum
4074literal type might not compare equal to itself.
0 commit comments