Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
bpo-46475: Add typing.Never and typing.assert_never#30842
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
86a868f4b227f6403f8e5d3cc0f596214931b297fe02a3e89b3f4ccb2530bd7c23cc264497a26c7319771f6b671File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -574,6 +574,34 @@ These can be used as types in annotations and do not support ``[]``. | ||
| * Every type is compatible with :data:`Any`. | ||
| * :data:`Any` is compatible with every type. | ||
| .. data:: Never | ||
| The `bottom type <https://en.wikipedia.org/wiki/Bottom_type>`_, | ||
| a type that has no members. | ||
| This can be used to define a function that should never be | ||
| called, or a function that never returns:: | ||
| from typing import Never | ||
| def never_call_me(arg: Never) -> None: | ||
| pass | ||
| def int_or_str(arg: int | str) -> None: | ||
| never_call_me(arg) # type checker error | ||
| match arg: | ||
| case int(): | ||
| print("It's an int") | ||
| case str(): | ||
| print("It's a str") | ||
| case _: | ||
| never_call_me(arg) # ok, arg is of type Never | ||
| .. versionadded:: 3.11 | ||
| On older Python versions, :data:`NoReturn` may be used to express the | ||
| same concept. ``Never`` was added to make the intended meaning more explicit. | ||
| .. data:: NoReturn | ||
JelleZijlstra marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Special type indicating that a function never returns. | ||
| @@ -584,6 +612,12 @@ These can be used as types in annotations and do not support ``[]``. | ||
| def stop() -> NoReturn: | ||
| raise RuntimeError('no way') | ||
| ``NoReturn`` can also be used as a | ||
| `bottom type <https://en.wikipedia.org/wiki/Bottom_type>`_, a type that | ||
| has no values. Starting in Python 3.11, the :data:`Never` type should | ||
| be used for this concept instead. Type checkers should treat the two | ||
| equivalently. | ||
| .. versionadded:: 3.5.4 | ||
| .. versionadded:: 3.6.2 | ||
| @@ -1979,6 +2013,28 @@ Functions and decorators | ||
| runtime we intentionally don't check anything (we want this | ||
| to be as fast as possible). | ||
| .. function:: assert_never(arg, /) | ||
| Assert to the type checker that a line of code is unreachable. | ||
| Example:: | ||
| def int_or_str(arg: int | str) -> None: | ||
| match arg: | ||
| case int(): | ||
| print("It's an int") | ||
| case str(): | ||
| print("It's a str") | ||
| case _ as unreachable: | ||
| assert_never(unreachable) | ||
| If a type checker finds that a call to ``assert_never()`` is | ||
| reachable, it will emit an error. | ||
| At runtime, this throws an exception when called. | ||
| .. versionadded:: 3.11 | ||
| .. function:: reveal_type(obj) | ||
| Reveal the inferred static type of an expression. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -5,7 +5,7 @@ | ||
| * Imports and exports, all public names should be explicitly added to __all__. | ||
| * Internal helper functions: these should never be used in code outside this module. | ||
| * _SpecialForm and its instances (special forms): | ||
| Any, NoReturn, ClassVar, Union, Optional, Concatenate | ||
| Any, NoReturn, Never, ClassVar, Union, Optional, Concatenate | ||
| * Classes whose instances can be type arguments in addition to types: | ||
| ForwardRef, TypeVar and ParamSpec | ||
| * The core of internal generics API: _GenericAlias and _VariadicGenericAlias, the latter is | ||
| @@ -117,12 +117,14 @@ def _idfunc(_, x): | ||
| # One-off things. | ||
| 'AnyStr', | ||
| 'assert_never', | ||
| 'cast', | ||
| 'final', | ||
| 'get_args', | ||
| 'get_origin', | ||
| 'get_type_hints', | ||
| 'is_typeddict', | ||
| 'Never', | ||
| 'NewType', | ||
| 'no_type_check', | ||
| 'no_type_check_decorator', | ||
| @@ -175,7 +177,7 @@ def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms= | ||
| if (isinstance(arg, _GenericAlias) and | ||
| arg.__origin__ in invalid_generic_forms): | ||
| raise TypeError(f"{arg} is not valid as type argument") | ||
| if arg in (Any, NoReturn, Self, ClassVar, Final, TypeAlias): | ||
| if arg in (Any, NoReturn, Never, Self, ClassVar, Final, TypeAlias): | ||
| return arg | ||
| if isinstance(arg, _SpecialForm) or arg in (Generic, Protocol): | ||
| raise TypeError(f"Plain {arg} is not valid as type argument") | ||
| @@ -441,8 +443,39 @@ def NoReturn(self, parameters): | ||
| def stop() -> NoReturn: | ||
| raise Exception('no way') | ||
| This type is invalid in other positions, e.g., ``List[NoReturn]`` | ||
| will fail in static type checkers. | ||
| NoReturn can also be used as a bottom type, a type that | ||
| has no values. Starting in Python 3.11, the Never type should | ||
| be used for this concept instead. Type checkers should treat the two | ||
| equivalently. | ||
| """ | ||
| raise TypeError(f"{self} is not subscriptable") | ||
| # This is semantically identical to NoReturn, but it is implemented | ||
| # separately so that type checkers can distinguish between the two | ||
| # if they want. | ||
| @_SpecialForm | ||
| def Never(self, parameters): | ||
JelleZijlstra marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| """The bottom type, a type that has no members. | ||
| This can be used to define a function that should never be | ||
| called, or a function that never returns:: | ||
| from typing import Never | ||
| def never_call_me(arg: Never) -> None: | ||
| pass | ||
| def int_or_str(arg: int | str) -> None: | ||
| never_call_me(arg) # type checker error | ||
| match arg: | ||
| case int(): | ||
| print("It's an int") | ||
| case str(): | ||
| print("It's a str") | ||
| case _: | ||
| never_call_me(arg) # ok, arg is of type Never | ||
| """ | ||
| raise TypeError(f"{self} is not subscriptable") | ||
| @@ -2050,6 +2083,29 @@ class Film(TypedDict): | ||
| return isinstance(tp, _TypedDictMeta) | ||
| def assert_never(arg: Never, /) -> Never: | ||
| """Statically assert that a line of code is unreachable. | ||
| Example:: | ||
| def int_or_str(arg: int | str) -> None: | ||
| match arg: | ||
| case int(): | ||
| print("It's an int") | ||
| case str(): | ||
| print("It's a str") | ||
| case _: | ||
| assert_never(arg) | ||
| If a type checker finds that a call to assert_never() is | ||
| reachable, it will emit an error. | ||
Comment on lines
+2091
to
+2101
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This example is much better than the examples in the main doc. :-) And so is the sentence following the example. MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sentence is also in the docs for assert_never, but not Never. I'm pushing some changes to improve the Never docs according to your feedback. Honestly I'm a bit confused about the relationship between the docstring and the RST docs. I end up copying from one to the other. Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usually the docstring is shorter, since it is often displayed by tools that have limited output space (it's really annoying to get a scroll bar in a tooltip in VS Code :-). | ||
| At runtime, this throws an exception when called. | ||
| """ | ||
| raise AssertionError("Expected code to be unreachable") | ||
gvanrossum marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| def no_type_check(arg): | ||
| """Decorator to indicate that annotations are not type hints. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Add :data:`typing.Never` and :func:`typing.assert_never`. Patch by Jelle | ||
| Zijlstra. |
Uh oh!
There was an error while loading. Please reload this page.