-
Notifications
You must be signed in to change notification settings - Fork 226
Description
Here's what these types represent:
tuple: the set of all possible runtime instances of the classtuple(including instances of tuple subclasses)AlwaysFalsy: the set of all possible runtime objects whose truthiness can be statically determined to always be falsetuple[()]: the set of all possible zero-length tuples (including zero-length instances of tuple subclasses)tuple & AlwaysFalsy: the set of all possible runtime instances of the classtuple(including instances of tuple subclasses) whose truthiness can be statically determined to always be false
Tuple instances (and instances of any tuple subclass, assuming the subclass conforms to the Liskov principle) are only ever falsy if they are 0-length, so the set of possible objects represented by tuple & AlwaysFalsy is exactly the same as the set of possible objects represented by tuple[()]. By the same token, .tuple & ~AlwaysTruthy should also simplify to tuple[()]
The same can not be said for things like bytes & AlwaysFalsy (this does not simplify to Literal[b""]), because bytes can be subclassed, and instances of bytes subclasses can also be falsy if they are empty bytestrings, but for a type to inhabit a literal bytes type its __class__ must be exactly bytes, not a subclass of bytes. Heterogeneous tuple types are different from Literal types in this way, in that they can be inhabited by subclasses of tuple as well as literal tuples.
We should adapt the logic in InnerIntersectionBuilder to eagerly perform this simplification when we see the intersection tuple & AlwaysFalsy.