You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.)
The text was updated successfully, but these errors were encountered:
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 tofunc(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 atypedef
to avoid this. For variable declarations, these or-annotations can probably be ignored.func(x: A | B | None)
: same as above, but requiresA
andB
to have Python types in order to allowNone
.isinstance(x, A | B)
/issubclass(x, A | B)
: this is not so obvious becauseA | 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 withNone
returns a type. It's very tempting, though, given how cheap aNone
check is in C.x: A | None
: this requiresA
to be a Python type in order to acceptNone
values. This probably shouldn't have any other effect, since object variables are generally allowed to beNone
.x: A | B
: this probably should not have an effect currently since we would not considerA | 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)
andT = cython.fused_type(A | B)
should be allowed and both define a fused type.x = cython.declare(A | B)
should declarex
as a fused type. This should be disallowed for globals and in class bodies.Open questions:
func(x: A | B, y: A | B)
to have one or two fused types? (Probably two, as before.)__annotations__
value inx: A | B
totyping.Union[A, B]
? (Maybe yes, because it's more backwards compatible. Maybe not, since users can spell this out themselves.)func(x: Union[A, B])
also a fused function now? (Maybe yes, for consistency.)T = Union[A, B]
the same asT = cython.fused_type(A, B)
? (Maybe yes, for consistency. Maybe no, for safety.)x: A | None
allowA
to bedouble
orbint
, which we internally alias for Pythonfloat
andbool
? (Maybe not right now.)isinstance()
on Cython fused type names? (Maybe not as part of this ticket.)The text was updated successfully, but these errors were encountered: