@@ -721,6 +721,75 @@ static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[""]]], No
721
721
static_assert(is_assignable_to(Intersection[LiteralString, Not[Literal[" " , " a" ]]], Not[AlwaysFalsy]))
722
722
```
723
723
724
+ ## Intersections with non-fully-static negated elements
725
+
726
+ A type can be _ assignable_ to an intersection containing negated elements only if the _ bottom_
727
+ materialization of that type is disjoint from the _ bottom_ materialization of all negated elements
728
+ in the intersection. This differs from subtyping, which should do the disjointness check against the
729
+ _ top_ materialization of the negated elements.
730
+
731
+ ``` py
732
+ from typing_extensions import Any, Never, Sequence
733
+ from ty_extensions import Not, is_assignable_to, static_assert
734
+
735
+ # The bottom materialization of `tuple[Any]` is `tuple[Never]`,
736
+ # which simplifies to `Never`, so `tuple[int]` and `tuple[()]` are
737
+ # both assignable to `~tuple[Any]`
738
+ static_assert(is_assignable_to(tuple[int ], Not[tuple[Any]]))
739
+ static_assert(is_assignable_to(tuple[()], Not[tuple[Any]]))
740
+
741
+ # But the bottom materialization of `tuple[Any, ...]` is `tuple[Never, ...]`,
742
+ # which simplifies to `tuple[()]`, so `tuple[int]` is still assignable to
743
+ # `~tuple[Any, ...]`, but `tuple[()]` is not
744
+ static_assert(is_assignable_to(tuple[int ], Not[tuple[Any, ... ]]))
745
+ static_assert(not is_assignable_to(tuple[()], Not[tuple[Any, ... ]]))
746
+
747
+ # Similarly, the bottom materialization of `Sequence[Any]` is `Sequence[Never]`,
748
+ # so `tuple[()]` is not assignable to `~Sequence[Any]`, and nor is `list[Never]`,
749
+ # since both `tuple[()]` and `list[Never]` are subtypes of `Sequence[Never]`.
750
+ # `tuple[int, ...]` is also not assignable to `~Sequence[Any]`, as although it is
751
+ # not a subtype of `Sequence[Never]` it is also not disjoint from `Sequence[Never]`:
752
+ # `tuple[()]` is a subtype of both `Sequence[Never]` and `tuple[int, ...]`, so
753
+ # `tuple[int, ...]` and `Sequence[Never]` cannot be considered disjoint.
754
+ #
755
+ # Other `list` and `tuple` specializations *are* assignable to `~Sequence[Any]`,
756
+ # however, since there are many fully static materializations of `Sequence[Any]`
757
+ # that would be disjoint from a given `list` or `tuple` specialization.
758
+ static_assert(not is_assignable_to(tuple[()], Not[Sequence[Any]]))
759
+ static_assert(not is_assignable_to(list[Never], Not[Sequence[Any]]))
760
+ static_assert(not is_assignable_to(tuple[int , ... ], Not[Sequence[Any]]))
761
+
762
+ # TODO : should pass (`tuple[int]` should be considered disjoint from `Sequence[Never]`)
763
+ static_assert(is_assignable_to(tuple[int ], Not[Sequence[Any]])) # error: [static-assert-error]
764
+
765
+ # TODO : should pass (`list[int]` should be considered disjoint from `Sequence[Never]`)
766
+ static_assert(is_assignable_to(list[int ], Not[Sequence[Any]])) # error: [static-assert-error]
767
+
768
+ # If the left-hand side is also not fully static,
769
+ # the left-hand side will be assignable to the right if the bottom materialization
770
+ # of the left-hand side is disjoint from the bottom materialization of all negated
771
+ # elements on the right-hand side
772
+
773
+ # `tuple[Any, ...]` cannot be assignable to `~tuple[Any, ...]`,
774
+ # because the bottom materialization of `tuple[Any, ...]` is
775
+ # `tuple[()]`, and `tuple[()]` is not disjoint from itself
776
+ static_assert(not is_assignable_to(tuple[Any, ... ], Not[tuple[Any, ... ]]))
777
+
778
+ # but `tuple[Any]` is assignable to `~tuple[Any]`,
779
+ # as the bottom materialization of `tuple[Any]` is `Never`,
780
+ # and `Never` *is* disjoint from itself
781
+ static_assert(is_assignable_to(tuple[Any], Not[tuple[Any]]))
782
+
783
+ # The same principle applies for non-fully-static `list` specializations.
784
+ # TODO : this should pass (`Bottom[list[Any]]` should simplify to `Never`)
785
+ static_assert(is_assignable_to(list[Any], Not[list[Any]])) # error: [static-assert-error]
786
+
787
+ # `Bottom[list[Any]]` is `Never`, which is disjoint from `Bottom[Sequence[Any]]`
788
+ # (which is `Sequence[Never]`).
789
+ # TODO : this should pass (`Bottom[list[Any]]` should simplify to `Never`)
790
+ static_assert(is_assignable_to(list[Any], Not[Sequence[Any]])) # error: [static-assert-error]
791
+ ```
792
+
724
793
## General properties
725
794
726
795
See also: our property tests in ` property_tests.rs ` .
0 commit comments