Skip to content

Commit fd29b4d

Browse files
check if current_type is AnyType
1 parent 74db0aa commit fd29b4d

File tree

3 files changed

+52
-31
lines changed

3 files changed

+52
-31
lines changed

mypy/checker.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7994,11 +7994,13 @@ def conditional_types(
79947994
) -> tuple[Type | None, Type | None]:
79957995
"""Takes in the current type and a proposed type of an expression.
79967996
7997-
Returns a 2-tuple: The first element is the proposed type, if the expression
7998-
can be the proposed type. The second element is the type it would hold
7999-
if it was not the proposed type, if any. UninhabitedType means unreachable.
8000-
None means no new information can be inferred. If default is set it is returned
8001-
instead."""
7997+
Returns a 2-tuple:
7998+
The first element is the proposed type, if the expression can be the proposed type.
7999+
The second element is the type it would hold if it was not the proposed type, if any.
8000+
UninhabitedType means unreachable.
8001+
None means no new information can be inferred.
8002+
If default is set it is returned instead.
8003+
"""
80028004
if proposed_type_ranges:
80038005
if len(proposed_type_ranges) == 1:
80048006
target = proposed_type_ranges[0].item
@@ -8010,24 +8012,26 @@ def conditional_types(
80108012
current_type = try_expanding_sum_type_to_union(current_type, enum_name)
80118013
proposed_items = [type_range.item for type_range in proposed_type_ranges]
80128014
proposed_type = make_simplified_union(proposed_items)
8013-
if isinstance(proposed_type, AnyType):
8015+
current_type = get_proper_type(current_type)
8016+
if isinstance(proposed_type, AnyType) or isinstance(current_type, AnyType):
80148017
# We don't really know much about the proposed type, so we shouldn't
80158018
# attempt to narrow anything. Instead, we broaden the expr to Any to
80168019
# avoid false positives
80178020
return proposed_type, default
8018-
elif not any(
8021+
elif not any( # handle concrete subtypes
80198022
type_range.is_upper_bound for type_range in proposed_type_ranges
8020-
) and ( # concrete subtypes
8021-
is_proper_subtype(current_type, proposed_type, ignore_promotions=True)
8022-
or ( # structural subtypes
8023-
is_subtype(current_type, proposed_type, ignore_promotions=True)
8024-
and (
8025-
isinstance(proposed_type, CallableType)
8026-
or (isinstance(proposed_type, Instance) and proposed_type.type.is_protocol)
8027-
)
8023+
) and is_proper_subtype(current_type, proposed_type, ignore_promotions=True):
8024+
# Expression is always of one of the types in proposed_type_ranges
8025+
return default, UninhabitedType()
8026+
elif not any( # handle structural subtypes
8027+
type_range.is_upper_bound for type_range in proposed_type_ranges
8028+
) and (
8029+
is_subtype(current_type, proposed_type, ignore_promotions=True)
8030+
and (
8031+
isinstance(proposed_type, CallableType)
8032+
or (isinstance(proposed_type, Instance) and proposed_type.type.is_protocol)
80288033
)
80298034
):
8030-
# Expression is always of one of the types in proposed_type_ranges
80318035
return default, UninhabitedType()
80328036
elif not is_overlapping_types(current_type, proposed_type, ignore_promotions=True):
80338037
# Expression is never of any type in proposed_type_ranges

test-data/unit/check-generic-alias.test

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,38 @@ t23: collections.abc.ValuesView[str]
149149
# reveal_type(t23) # Nx Revealed type is "collections.abc.ValuesView[builtins.str]"
150150
[builtins fixtures/tuple.pyi]
151151

152+
[case testGenericAliasIsinstanceUnreachable]
153+
# flags: --warn-unreachable --python-version 3.10
154+
from collections.abc import Iterable
155+
156+
class A: ...
157+
158+
def test(dependencies: list[A] | None) -> None:
159+
if dependencies is None:
160+
dependencies = []
161+
elif not isinstance(dependencies, Iterable):
162+
dependencies = [dependencies] # E: Statement is unreachable
163+
164+
[builtins fixtures/isinstancelist.pyi]
165+
[typing fixtures/typing-full.pyi]
166+
167+
[case testGenericAliasRedundantExprCompoundIfExpr]
168+
# flags: --warn-unreachable --enable-error-code=redundant-expr --python-version 3.10
169+
170+
from typing import Any, reveal_type
171+
from collections.abc import Iterable
172+
173+
def test_example(x: Iterable[Any]) -> None:
174+
if isinstance(x, Iterable) and not isinstance(x, str): # E: Left operand of "and" is always true
175+
reveal_type(x) # N: Revealed type is "typing.Iterable[Any]"
176+
177+
def test_counterexample(x: Any) -> None:
178+
if isinstance(x, Iterable) and not isinstance(x, str):
179+
reveal_type(x) # N: Revealed type is "typing.Iterable[Any]"
180+
181+
[builtins fixtures/isinstancelist.pyi]
182+
[typing fixtures/typing-full.pyi]
183+
152184

153185
[case testGenericBuiltinTupleTyping]
154186
from typing import Tuple

test-data/unit/check-isinstance.test

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,21 +1086,6 @@ while bool():
10861086
x + 'a'
10871087
[builtins fixtures/isinstance.pyi]
10881088

1089-
[case testUnreachableCode3]
1090-
# flags: --warn-unreachable --python-version 3.10
1091-
from collections.abc import Iterable
1092-
1093-
class A: ...
1094-
1095-
def test(dependencies: list[A] | None) -> None:
1096-
if dependencies is None:
1097-
dependencies = []
1098-
elif not isinstance(dependencies, Iterable):
1099-
dependencies = [dependencies] # E: Statement is unreachable
1100-
1101-
[builtins fixtures/isinstancelist.pyi]
1102-
[typing fixtures/typing-full.pyi]
1103-
11041089
[case testUnreachableWhileTrue]
11051090
def f(x: int) -> None:
11061091
while True:

0 commit comments

Comments
 (0)