Skip to content

Commit ec08f1f

Browse files
committed
Let issubclass narrow Any
Fixes #10680
1 parent e5cd1f9 commit ec08f1f

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

mypy/checker.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7860,7 +7860,6 @@ def push_type_map(self, type_map: TypeMap, *, from_assignment: bool = True) -> N
78607860
def infer_issubclass_maps(self, node: CallExpr, expr: Expression) -> tuple[TypeMap, TypeMap]:
78617861
"""Infer type restrictions for an expression in issubclass call."""
78627862
vartype = self.lookup_type(expr)
7863-
type = self.get_isinstance_type(node.args[1])
78647863
if isinstance(vartype, TypeVarType):
78657864
vartype = vartype.upper_bound
78667865
vartype = get_proper_type(vartype)
@@ -7876,13 +7875,16 @@ def infer_issubclass_maps(self, node: CallExpr, expr: Expression) -> tuple[TypeM
78767875
vartype = UnionType(union_list)
78777876
elif isinstance(vartype, TypeType):
78787877
vartype = vartype.item
7878+
elif isinstance(vartype, AnyType):
7879+
pass
78797880
elif isinstance(vartype, Instance) and vartype.type.is_metaclass():
78807881
vartype = self.named_type("builtins.object")
78817882
else:
7882-
# Any other object whose type we don't know precisely
7883-
# for example, Any or a custom metaclass.
7884-
return {}, {} # unknown type
7885-
yes_type, no_type = self.conditional_types_with_intersection(vartype, type, expr)
7883+
# Any other object which isn't a type
7884+
return {}, {}
7885+
7886+
issubclass_type = self.get_isinstance_type(node.args[1])
7887+
yes_type, no_type = self.conditional_types_with_intersection(vartype, issubclass_type, expr)
78867888
yes_map, no_map = conditional_types_to_typemaps(expr, yes_type, no_type)
78877889
yes_map, no_map = map(convert_to_typetype, (yes_map, no_map))
78887890
return yes_map, no_map

test-data/unit/check-isinstance.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,25 @@ def directed_meet(cls0: ClassT, cls1: ClassT) -> ClassT | None:
18671867
return None
18681868
[builtins fixtures/isinstancelist.pyi]
18691869

1870+
[case testIssubclassAny]
1871+
# flags: --warn-unreachable
1872+
from typing import Any
1873+
1874+
def f1(x: Any) -> None:
1875+
if issubclass(x, int):
1876+
reveal_type(x) # N: Revealed type is "type[builtins.int]"
1877+
else:
1878+
reveal_type(x) # N: Revealed type is "Any"
1879+
reveal_type(x) # N: Revealed type is "Any"
1880+
1881+
def f2(x: Any) -> None:
1882+
if issubclass(x, list):
1883+
reveal_type(x) # N: Revealed type is "type[builtins.list[Any]]"
1884+
else:
1885+
reveal_type(x) # N: Revealed type is "Any"
1886+
reveal_type(x) # N: Revealed type is "Any"
1887+
[builtins fixtures/isinstancelist.pyi]
1888+
18701889
[case testIsinstanceTypeArgs]
18711890
# flags: --warn-unreachable
18721891
from typing import Iterable, TypeVar

0 commit comments

Comments
 (0)