diff --git a/mypy/checker.py b/mypy/checker.py index 8720b4995f36..842a4a3d25a5 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3895,12 +3895,15 @@ def conditional_type_map(expr: Expression, second element is a map from the expression to the type it would hold if it was not the proposed type, if any. None means bot, {} means top""" if proposed_type_ranges: - if len(proposed_type_ranges) == 1: - proposed_type = proposed_type_ranges[0].item # Union with a single type breaks tests - else: - proposed_type = UnionType([type_range.item for type_range in proposed_type_ranges]) + proposed_items = [type_range.item for type_range in proposed_type_ranges] + proposed_type = UnionType.make_simplified_union(proposed_items) if current_type: - if (not any(type_range.is_upper_bound for type_range in proposed_type_ranges) + if isinstance(proposed_type, AnyType): + # We don't really know much about the proposed type, so we shouldn't + # attempt to narrow anything. Instead, we broaden the expr to Any to + # avoid false positives + return {expr: proposed_type}, {} + elif (not any(type_range.is_upper_bound for type_range in proposed_type_ranges) and is_proper_subtype(current_type, proposed_type)): # Expression is always of one of the types in proposed_type_ranges return {}, None diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 0b80a74c0110..ca3b2fb176ea 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -2101,6 +2101,34 @@ def f(x: Union[A, str]) -> None: x.method_only_in_a() [builtins fixtures/isinstance.pyi] +[case testIsinstanceIgnoredImportDualAny] +from typing import Any +from foo import Bad, OtherBad # type: ignore +x: Any +if isinstance(x, Bad): + reveal_type(x) # N: Revealed type is 'Any' +else: + reveal_type(x) # N: Revealed type is 'Any' + +if isinstance(x, (Bad, OtherBad)): + reveal_type(x) # N: Revealed type is 'Any' +else: + reveal_type(x) # N: Revealed type is 'Any' + +y: object +if isinstance(y, Bad): + reveal_type(y) # N: Revealed type is 'Any' +else: + reveal_type(y) # N: Revealed type is 'builtins.object' + +class Ok: pass +z: Any +if isinstance(z, Ok): + reveal_type(z) # N: Revealed type is '__main__.Ok' +else: + reveal_type(z) # N: Revealed type is 'Any' +[builtins fixtures/isinstance.pyi] + [case testIsInstanceInitialNoneCheckSkipsImpossibleCasesNoStrictOptional] # flags: --strict-optional from typing import Optional, Union