Skip to content

Commit b4b8d74

Browse files
authored
Improve sentinel narrowing (#21844)
Followup to #21647 Adjust test case for equality narrowing. That's already implemented, the test was just using a striped down fixture. Also add support for narrowing sentinels with `in` and collections similar to enums.
1 parent 6eb141f commit b4b8d74

3 files changed

Lines changed: 16 additions & 5 deletions

File tree

mypy/typeops.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from mypy.types import (
3838
ELLIPSIS_TYPE_NAMES,
3939
NOT_IMPLEMENTED_TYPE_NAMES,
40+
SENTINEL_TYPE_NAMES,
4041
AnyType,
4142
CallableType,
4243
ExtraAttrs,
@@ -1056,6 +1057,7 @@ def is_singleton_identity_type(typ: ProperType) -> bool:
10561057
(typ.type.is_enum and len(typ.type.enum_members) == 1)
10571058
or (typ.type.fullname in ELLIPSIS_TYPE_NAMES)
10581059
or (typ.type.fullname in NOT_IMPLEMENTED_TYPE_NAMES)
1060+
or (typ.type.fullname in SENTINEL_TYPE_NAMES)
10591061
)
10601062
if isinstance(typ, LiteralType):
10611063
return typ.is_enum_literal() or typ.is_sentinel_literal() or isinstance(typ.value, bool)

test-data/unit/check-sentinels.test

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,22 @@ MISSING = Sentinel("MISSING")
3636
SPECIAL = Sentinel("SPECIAL")
3737

3838
def func(x: int | MISSING | SPECIAL) -> None:
39-
# We could reasonably do narrowing here, but currently we're pretty conservative
40-
# about narrowing on ==.
4139
if x == MISSING:
42-
assert_type(x, int | MISSING | SPECIAL)
40+
assert_type(x, MISSING)
41+
else:
42+
assert_type(x, int | SPECIAL)
43+
[builtins fixtures/ops.pyi]
44+
45+
[case testSentinelNarrowingInSequence]
46+
from typing_extensions import assert_type, Sentinel
47+
48+
MISSING = Sentinel("MISSING")
49+
50+
def func(var: str | MISSING | None) -> None:
51+
if var in (MISSING, None):
52+
assert_type(var, MISSING | None)
4353
else:
44-
assert_type(x, int | MISSING | SPECIAL)
54+
assert_type(var, str)
4555
[builtins fixtures/tuple.pyi]
4656

4757
[case testSentinelSameReprDistinctTypes]

test-data/unit/lib-stub/typing_extensions.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Never: _SpecialForm
4444

4545
class Sentinel:
4646
def __init__(self, name: str, repr: str | None = None) -> None: ...
47-
def __eq__(self, other: object) -> bool: ...
4847
sentinel = Sentinel
4948

5049
TypeVarTuple: _SpecialForm

0 commit comments

Comments
 (0)