diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 4fbb592aa..fdfcb518f 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -186,6 +186,8 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st else: return f':py:class:`{cls.__name__}`' elif UnionType and isinstance(cls, UnionType): + # Union types (PEP 585) retain their definition order when they + # are printed natively and ``None``-like types are kept as is. return ' | '.join(restify(a, mode) for a in cls.__args__) elif cls.__module__ in ('__builtin__', 'builtins'): if hasattr(cls, '__args__'): @@ -199,6 +201,7 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st elif (inspect.isgenericalias(cls) and cls.__module__ == 'typing' and cls.__origin__ is Union): # type: ignore[attr-defined] + # *cls* is defined in ``typing``, and thus ``__args__`` must exist return ' | '.join(restify(a, mode) for a in cls.__args__) # type: ignore[attr-defined] elif inspect.isgenericalias(cls): if isinstance(cls.__origin__, typing._SpecialForm): # type: ignore[attr-defined]