Skip to content

Commit

Permalink
Add support for Never (#12153)
Browse files Browse the repository at this point in the history
  • Loading branch information
JelleZijlstra committed Feb 9, 2022
1 parent 234344b commit 6ff8091
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 9 deletions.
8 changes: 2 additions & 6 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
from mypy.errorcodes import ErrorCode
from mypy import message_registry, errorcodes as codes
from mypy.types import (
FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType,
NEVER_NAMES, FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType,
CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue,
TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType,
get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType,
Expand Down Expand Up @@ -2227,11 +2227,7 @@ def is_type_ref(self, rv: Expression, bare: bool = False) -> bool:
# Assignment color = Color['RED'] defines a variable, not an alias.
return not rv.node.is_enum
if isinstance(rv.node, Var):
return rv.node.fullname in (
'typing.NoReturn',
'typing_extensions.NoReturn',
'mypy_extensions.NoReturn',
)
return rv.node.fullname in NEVER_NAMES

if isinstance(rv, NameExpr):
n = self.lookup(rv.name, rv)
Expand Down
4 changes: 2 additions & 2 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from mypy.messages import MessageBuilder, quote_type_string, format_type_bare
from mypy.options import Options
from mypy.types import (
Type, UnboundType, TupleType, TypedDictType, UnionType, Instance, AnyType,
NEVER_NAMES, Type, UnboundType, TupleType, TypedDictType, UnionType, Instance, AnyType,
CallableType, NoneType, ErasedType, DeletedType, TypeList, TypeVarType, SyntheticTypeVisitor,
StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument,
TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType,
Expand Down Expand Up @@ -348,7 +348,7 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt
self.fail('ClassVar[...] must have at most one type argument', t)
return AnyType(TypeOfAny.from_error)
return self.anal_type(t.args[0])
elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'):
elif fullname in NEVER_NAMES:
return UninhabitedType(is_noreturn=True)
elif fullname in LITERAL_TYPE_NAMES:
return self.analyze_literal_type(t)
Expand Down
8 changes: 8 additions & 0 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@
'typing_extensions.reveal_type',
)

NEVER_NAMES: Final = (
'typing.NoReturn',
'typing_extensions.NoReturn',
'mypy_extensions.NoReturn',
'typing.Never',
'typing_extensions.Never',
)

# A placeholder used for Bogus[...] parameters
_dummy: Final[Any] = object()

Expand Down
20 changes: 20 additions & 0 deletions test-data/unit/check-unreachable-code.test
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,26 @@ if False:
reveal_type(x)
[builtins fixtures/exception.pyi]

[case testNeverVariants]
from typing import Never
from typing_extensions import Never as TENever
from typing import NoReturn
from typing_extensions import NoReturn as TENoReturn
from mypy_extensions import NoReturn as MENoReturn

bottom1: Never
reveal_type(bottom1) # N: Revealed type is "<nothing>"
bottom2: TENever
reveal_type(bottom2) # N: Revealed type is "<nothing>"
bottom3: NoReturn
reveal_type(bottom3) # N: Revealed type is "<nothing>"
bottom4: TENoReturn
reveal_type(bottom4) # N: Revealed type is "<nothing>"
bottom5: MENoReturn
reveal_type(bottom5) # N: Revealed type is "<nothing>"

[builtins fixtures/tuple.pyi]

[case testUnreachableFlagExpressions]
# flags: --warn-unreachable
def foo() -> bool: ...
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/lib-stub/typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Type = 0
ClassVar = 0
Final = 0
NoReturn = 0
Never = 0
NewType = 0
ParamSpec = 0

Expand Down
3 changes: 2 additions & 1 deletion test-data/unit/lib-stub/typing_extensions.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import TypeVar, Any, Mapping, Iterator, NoReturn, Dict, Type
from typing import TypeVar, Any, Mapping, Iterator, NoReturn as NoReturn, Dict, Type
from typing import TYPE_CHECKING as TYPE_CHECKING
from typing import NewType as NewType

Expand Down Expand Up @@ -27,6 +27,7 @@ Concatenate: _SpecialForm
TypeAlias: _SpecialForm

TypeGuard: _SpecialForm
Never: _SpecialForm

# Fallback type for all typed dicts (does not exist at runtime).
class _TypedDict(Mapping[str, object]):
Expand Down

0 comments on commit 6ff8091

Please sign in to comment.