@@ -5350,9 +5350,9 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
5350
5350
# an error, but returns the TypedDict type that matches the literal it found
5351
5351
# that would cause a second error when that TypedDict type is returned upstream
5352
5352
# to avoid the second error, we always return TypedDict type that was requested
5353
- typeddict_contexts = self .find_typeddict_context (self .type_context [- 1 ], e )
5353
+ typeddict_contexts , exhaustive = self .find_typeddict_context (self .type_context [- 1 ], e )
5354
5354
if typeddict_contexts :
5355
- if len (typeddict_contexts ) == 1 :
5355
+ if len (typeddict_contexts ) == 1 and exhaustive :
5356
5356
return self .check_typeddict_literal_in_context (e , typeddict_contexts [0 ])
5357
5357
# Multiple items union, check if at least one of them matches cleanly.
5358
5358
for typeddict_context in typeddict_contexts :
@@ -5363,7 +5363,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
5363
5363
self .chk .store_types (tmap )
5364
5364
return ret_type
5365
5365
# No item matched without an error, so we can't unambiguously choose the item.
5366
- self .msg .typeddict_context_ambiguous (typeddict_contexts , e )
5366
+ if exhaustive :
5367
+ self .msg .typeddict_context_ambiguous (typeddict_contexts , e )
5367
5368
5368
5369
# fast path attempt
5369
5370
dt = self .fast_dict_type (e )
@@ -5425,22 +5426,29 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
5425
5426
5426
5427
def find_typeddict_context (
5427
5428
self , context : Type | None , dict_expr : DictExpr
5428
- ) -> list [TypedDictType ]:
5429
+ ) -> tuple [list [TypedDictType ], bool ]:
5430
+ """Extract `TypedDict` members of the enclosing context.
5431
+
5432
+ Returns:
5433
+ a 2-tuple, (found_candidates, is_exhaustive)
5434
+ """
5429
5435
context = get_proper_type (context )
5430
5436
if isinstance (context , TypedDictType ):
5431
- return [context ]
5437
+ return [context ], True
5432
5438
elif isinstance (context , UnionType ):
5433
5439
items = []
5440
+ exhaustive = True
5434
5441
for item in context .items :
5435
- item_contexts = self .find_typeddict_context (item , dict_expr )
5442
+ item_contexts , item_exhaustive = self .find_typeddict_context (item , dict_expr )
5436
5443
for item_context in item_contexts :
5437
5444
if self .match_typeddict_call_with_dict (
5438
5445
item_context , dict_expr .items , dict_expr
5439
5446
):
5440
5447
items .append (item_context )
5441
- return items
5448
+ exhaustive = exhaustive and item_exhaustive
5449
+ return items , exhaustive
5442
5450
# No TypedDict type in context.
5443
- return []
5451
+ return [], False
5444
5452
5445
5453
def visit_lambda_expr (self , e : LambdaExpr ) -> Type :
5446
5454
"""Type check lambda expression."""
0 commit comments