From f1b97ed826e8f5a772e68739b10089995b061751 Mon Sep 17 00:00:00 2001 From: Jonathan Amponsah <82057176+mgalore@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:32:18 +0000 Subject: [PATCH] fix: preserve sentinels in dict get inference --- mypy/checkexpr.py | 12 +++++++++++- test-data/unit/check-sentinels.test | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 172d44555b946..1c85e33b8cc99 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2054,7 +2054,17 @@ def infer_arg_types_in_context( # cases. A cleaner alternative would be to switch to single bin type # inference, but this is a lot of work. old = self.infer_more_unions_for_recursive_type(ctx) - res.append(self.accept(arg, ctx)) + arg_type = self.accept(arg, ctx) + proper_ctx = get_proper_type(ctx) + proper_arg_type = get_proper_type(arg_type) + if ( + isinstance(proper_ctx, TypeVarType) + and isinstance(proper_arg_type, Instance) + and proper_arg_type.last_known_value is not None + and proper_arg_type.last_known_value.is_sentinel_literal() + ): + arg_type = proper_arg_type.last_known_value + res.append(arg_type) # We need to manually restore union inference state, ugh. type_state.infer_unions = old else: diff --git a/test-data/unit/check-sentinels.test b/test-data/unit/check-sentinels.test index 6d39c11375bb5..6a4172b6c7b30 100644 --- a/test-data/unit/check-sentinels.test +++ b/test-data/unit/check-sentinels.test @@ -189,3 +189,13 @@ def func(x: int | MISSING = MISSING) -> None: func(MISSING) func(ALIAS) # E: Argument 1 to "func" has incompatible type "Sentinel"; expected "int | MISSING" [builtins fixtures/tuple.pyi] + +[case testDictGetPEP661SentinelDefault] +from typing_extensions import assert_type, sentinel + +Unknown = sentinel("Unknown") + +def func(d: dict[str, str]) -> None: + var = d.get("key", Unknown) + assert_type(var, str | Unknown) +[builtins fixtures/dict.pyi]