Skip to content

Commit 143f990

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

File tree

4 files changed

+98
-23
lines changed

4 files changed

+98
-23
lines changed

mypy/checker.py

Lines changed: 11 additions & 6 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,7 +8012,10 @@ 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(current_type, AnyType):
8017+
return proposed_type, current_type
8018+
elif isinstance(proposed_type, AnyType):
80148019
# We don't really know much about the proposed type, so we shouldn't
80158020
# attempt to narrow anything. Instead, we broaden the expr to Any to
80168021
# avoid false positives

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:

test-data/unit/check-python310.test

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,30 @@ match m:
1111
-- Literal Pattern --
1212

1313
[case testMatchLiteralPatternNarrows]
14+
# flags: --warn-unreachable
1415
m: object
1516

1617
match m:
1718
case 1:
1819
reveal_type(m) # N: Revealed type is "Literal[1]"
20+
case 2:
21+
reveal_type(m) # N: Revealed type is "Literal[2]"
22+
case other:
23+
reveal_type(other) # N: Revealed type is "builtins.object"
24+
25+
[case testMatchLiteralPatternNarrows2]
26+
# flags: --warn-unreachable
27+
from typing import Any
28+
29+
m: Any
30+
31+
match m:
32+
case 1:
33+
reveal_type(m) # N: Revealed type is "Literal[1]"
34+
case 2:
35+
reveal_type(m) # N: Revealed type is "Literal[2]"
36+
case other:
37+
reveal_type(other) # N: Revealed type is "Any"
1938

2039
[case testMatchLiteralPatternAlreadyNarrower-skip]
2140
m: bool
@@ -1070,28 +1089,42 @@ match m:
10701089
pass
10711090

10721091
[case testMatchClassPatternCallable]
1073-
from typing import Callable
1092+
# flags: --warn-unreachable
1093+
from typing import Callable, Any
10741094

10751095
class FnImpl:
10761096
def __call__(self, x: object, /) -> int: ...
10771097

1098+
def test_any(x: Any) -> None:
1099+
match x:
1100+
case Callable() as fn:
1101+
reveal_type(fn) # N: Revealed type is "def (*Any, **Any) -> Any"
1102+
case other:
1103+
reveal_type(other) # N: Revealed type is "Any"
1104+
10781105
def test_object(x: object) -> None:
10791106
match x:
10801107
case Callable() as fn:
10811108
reveal_type(fn) # N: Revealed type is "def (*Any, **Any) -> Any"
1109+
case other:
1110+
reveal_type(other) # N: Revealed type is "builtins.object"
10821111

10831112
def test_impl(x: FnImpl) -> None:
10841113
match x:
10851114
case Callable() as fn:
10861115
reveal_type(fn) # N: Revealed type is "__main__.FnImpl"
1116+
case other:
1117+
reveal_type(other) # E: Statement is unreachable
10871118

10881119
def test_callable(x: Callable[[object], int]) -> None:
10891120
match x:
10901121
case Callable() as fn:
10911122
reveal_type(fn) # N: Revealed type is "def (builtins.object) -> builtins.int"
1092-
1123+
case other:
1124+
reveal_type(other) # E: Statement is unreachable
10931125

10941126
[case testMatchClassPatternCallbackProtocol]
1127+
# flags: --warn-unreachable
10951128
from typing import Any, Callable
10961129
from typing_extensions import Protocol, runtime_checkable
10971130

@@ -1102,24 +1135,38 @@ class FnProto(Protocol):
11021135
class FnImpl:
11031136
def __call__(self, x: object, /) -> int: ...
11041137

1138+
def test_any(x: Any) -> None:
1139+
match x:
1140+
case FnProto() as fn:
1141+
reveal_type(fn) # N: Revealed type is "__main__.FnProto"
1142+
case other:
1143+
reveal_type(other) # N: Revealed type is "Any"
1144+
11051145
def test_object(x: object) -> None:
11061146
match x:
11071147
case FnProto() as fn:
11081148
reveal_type(fn) # N: Revealed type is "__main__.FnProto"
1149+
case other:
1150+
reveal_type(other) # N: Revealed type is "builtins.object"
11091151

11101152
def test_impl(x: FnImpl) -> None:
11111153
match x:
11121154
case FnProto() as fn:
11131155
reveal_type(fn) # N: Revealed type is "__main__.FnImpl"
1156+
case other:
1157+
reveal_type(other) # E: Statement is unreachable
11141158

11151159
def test_callable(x: Callable[[object], int]) -> None:
11161160
match x:
11171161
case FnProto() as fn:
11181162
reveal_type(fn) # N: Revealed type is "def (builtins.object) -> builtins.int"
1163+
case other:
1164+
reveal_type(other) # E: Statement is unreachable
11191165

11201166
[builtins fixtures/dict.pyi]
11211167

11221168
[case testMatchClassPatternAnyCallableProtocol]
1169+
# flags: --warn-unreachable
11231170
from typing import Any, Callable
11241171
from typing_extensions import Protocol, runtime_checkable
11251172

@@ -1134,16 +1181,22 @@ def test_object(x: object) -> None:
11341181
match x:
11351182
case AnyCallable() as fn:
11361183
reveal_type(fn) # N: Revealed type is "__main__.AnyCallable"
1184+
case other:
1185+
reveal_type(other) # N: Revealed type is "builtins.object"
11371186

11381187
def test_impl(x: FnImpl) -> None:
11391188
match x:
11401189
case AnyCallable() as fn:
11411190
reveal_type(fn) # N: Revealed type is "__main__.FnImpl"
1191+
case other:
1192+
reveal_type(other) # E: Statement is unreachable
11421193

11431194
def test_callable(x: Callable[[object], int]) -> None:
11441195
match x:
11451196
case AnyCallable() as fn:
11461197
reveal_type(fn) # N: Revealed type is "def (builtins.object) -> builtins.int"
1198+
case other:
1199+
reveal_type(other) # E: Statement is unreachable
11471200

11481201
[builtins fixtures/dict.pyi]
11491202

0 commit comments

Comments
 (0)