Skip to content

Commit 7189a23

Browse files
authored
Fix make_simplified_union for instances with last_known_value (#10373)
This fixes make_simplified_union if multiple instances of the same type but with different last_known_values are passed to it. Previously it would falsely keep the last_known_value of the first occurrence: ``` make_simplified_union([Literal[1]?, Literal[2]?]) # Results in Literal[1]? ``` With this change the last_known_value is taken into account before a type is removed from the union. ``` make_simplified_union([Literal[1]?, Literal[2]?]) # Union[Literal[1]?, Literal[2]?] make_simplified_union([Literal[1]?, int]) # builtins.int make_simplified_union([Literal[1]?, <nothing>]) # Literal[1]? ```
1 parent 3c91647 commit 7189a23

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

mypy/typeops.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@ def make_simplified_union(items: Sequence[Type],
367367
# Keep track of the truishness info for deleted subtypes which can be relevant
368368
cbt = cbf = False
369369
for j, tj in enumerate(items):
370-
if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased):
370+
if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased) and \
371+
is_redundant_literal_instance(ti, tj):
371372
# We found a redundant item in the union.
372373
removed.add(j)
373374
cbt = cbt or tj.can_be_true
@@ -805,3 +806,14 @@ def custom_special_method(typ: Type, name: str, check_all: bool = False) -> bool
805806
return True
806807
# TODO: support other types (see ExpressionChecker.has_member())?
807808
return False
809+
810+
811+
def is_redundant_literal_instance(general: ProperType, specific: ProperType) -> bool:
812+
if not isinstance(general, Instance) or general.last_known_value is None:
813+
return True
814+
if isinstance(specific, Instance) and specific.last_known_value == general.last_known_value:
815+
return True
816+
if isinstance(specific, UninhabitedType):
817+
return True
818+
819+
return False

test-data/unit/check-python38.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def f(x: int = (c := 4)) -> int:
268268
f(x=(y7 := 3))
269269
reveal_type(y7) # N: Revealed type is "builtins.int"
270270

271-
reveal_type((lambda: (y8 := 3) and y8)()) # N: Revealed type is "Literal[3]?"
271+
reveal_type((lambda: (y8 := 3) and y8)()) # N: Revealed type is "builtins.int"
272272
y8 # E: Name "y8" is not defined
273273

274274
y7 = 1.0 # E: Incompatible types in assignment (expression has type "float", variable has type "int")

0 commit comments

Comments
 (0)