Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Implement PEP-604 (union types as X | Y) as fused types #4631

Open
9 tasks
scoder opened this issue Feb 10, 2022 · 0 comments
Open
9 tasks

[ENH] Implement PEP-604 (union types as X | Y) as fused types #4631

scoder opened this issue Feb 10, 2022 · 0 comments

Comments

@scoder
Copy link
Contributor

scoder commented Feb 10, 2022

Python 3.10 comes with a new syntax for union types, as defined by PEP-604.

There are a couple of separate aspects to this:

  • func(x: atype | None): this is equivalent to func(x: Optional[atype]) (which is already supported).
  • func(x: A | B): this should be considered a fused type by Cython and implemented as such. The usual caveat of cross product explosion for multiple fused typed arguments applies and we should probably also require a typedef to avoid this. For variable declarations, these or-annotations can probably be ignored.
  • func(x: A | B | None): same as above, but requires A and B to have Python types in order to allow None.
  • isinstance(x, A | B) / issubclass(x, A | B): this is not so obvious because A | B may not be two types here but an arbitrary expression that just happens to return a type (or a tuple of types). Implementing this only for the case where we detect A and B as types in the compiler would lead to unpredictable behaviour.
  • isinstance(x, A | None): the same as above applies, A might simply be some object that, when |-ed with None returns a type. It's very tempting, though, given how cheap a None check is in C.
  • x: A | None: this requires A to be a Python type in order to accept None values. This probably shouldn't have any other effect, since object variables are generally allowed to be None.
  • x: A | B: this probably should not have an effect currently since we would not consider A | B to be a fused type here (even inside of a fused function, this would not refer to the same type as the fused arguments).
  • T = cython.typedef(A | B) and T = cython.fused_type(A | B) should be allowed and both define a fused type.
  • x = cython.declare(A | B) should declare x as a fused type. This should be disallowed for globals and in class bodies.

Open questions:

  • should we consider func(x: A | B, y: A | B) to have one or two fused types? (Probably two, as before.)
  • should we change the __annotations__ value in x: A | B to typing.Union[A, B]? (Maybe yes, because it's more backwards compatible. Maybe not, since users can spell this out themselves.)
  • should we consider func(x: Union[A, B]) also a fused function now? (Maybe yes, for consistency.)
  • should we consider T = Union[A, B] the same as T = cython.fused_type(A, B)? (Maybe yes, for consistency. Maybe no, for safety.)
  • should x: A | None allow A to be double or bint, which we internally alias for Python float and bool? (Maybe not right now.)
  • should we support isinstance() on Cython fused type names? (Maybe not as part of this ticket.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant