Hi Philippe and list,
Long time lurker here, I've had a few spare cycles at $work this week that I spent exploring an alternate implementation to PEP604 starting with the implementation from Philippe. I don't say "reference implementation", because it doesn't implement PEP604 faithfully, but it does try to implement it's goal. My thinking was that the "runtime" component to it only needs to support the isinstance/issubclass methods and so can be pretty minimal without need to import all the typing.py machinery. At which point, when actual type checking was done (anything in typing.py or mypy), the `union` type can be special cased, or promoted to a `typing.Union`.
I started by creating a built-in "union" type, that was a thin wrapper around a tuple, such that type.__or__ will return `union(lhs, rhs)` which stored the two items in a 2-length tuple. I also changed the methods in `typing.Union` to return a `union`. However, I hit my first issue: `int | int | str` would then return `union(int, union(int, str))`, whereas it should deduplicate the types. So, I implemented logic to detect and merge union | union, but changed the underlying data to a plain flat tuple. And the next issue I hit was that some of the other `typing.py` types weren't being detected as valid types (probably due to my limited understanding of the PyObject datastructure/flags), specifically, `int | "forwardref"`, I needed a way to signal to typing.py that I had a forwardref without importing it. This is where I changed my approach to the problem.
I wanted to find a way to have these metatypes (Union/TypeVar/ForwardRef) without re-implementing them in c, or importing them. My Idea was to change the builtin type to what I called a "shadow type". In the C layer it's just holds a tuple of objects/parameters, and has a type field to say what it is, then when in the type checking/typing.py layer, if it detects an object is a "shadowobject", then it promotes it to a full type. What I liked about this approach, is that for isinstance/issubclass, when it see a "shadowobject" it can just grab the underlying types from the shadowobject->params tuple and no import magic needs to happen. All of the type magic can be left to mypy/typing.py without much knowledge of the shadowobject. I've mostly got through this implementation with all but one test passing.
At this point, I've got as far as I can go without help, so I'm posting here, looking for feedback or discussion. I expect that maybe the next step should be me commenting on the PEP604 itself for implementation concerns regarding `_GenericAlias`?
Implementation is located at https://github.com/Naddiseo/cpython/tree/PEP604
Python-Dev mailing list -- firstname.lastname@example.org
To unsubscribe send an email to email@example.com
Message archived at https://firstname.lastname@example.org/message/P56ZE6USNIGCQU5PIOLKC65VHD5DM37U/
Code of Conduct: http://python.org/psf/codeofconduct/