Skip to content

Commit 6d2635d

Browse files
authored
Don't narrow Type[X] with a metaclass (#10424)
We could narrow `Type[T]` to `<nothing>` when tested against a metaclass, which is not useful. Now we don't do any narrowing in this case. Fixes #10423.
1 parent 4518b55 commit 6d2635d

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

mypy/meet.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
7474
return narrowed
7575
elif isinstance(declared, TypeType) and isinstance(narrowed, TypeType):
7676
return TypeType.make_normalized(narrow_declared_type(declared.item, narrowed.item))
77+
elif (isinstance(declared, TypeType)
78+
and isinstance(narrowed, Instance)
79+
and narrowed.type.is_metaclass()):
80+
# We'd need intersection types, so give up.
81+
return declared
7782
elif isinstance(declared, (Instance, TupleType, TypeType, LiteralType)):
7883
return meet_types(declared, narrowed)
7984
elif isinstance(declared, TypedDictType) and isinstance(narrowed, Instance):

test-data/unit/check-narrowing.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,3 +1053,23 @@ def f(d: Union[Foo, Bar]) -> None:
10531053
d['x']
10541054
reveal_type(d) # N: Revealed type is "TypedDict('__main__.Foo', {'tag': Literal[__main__.E.FOO], 'x': builtins.int})"
10551055
[builtins fixtures/dict.pyi]
1056+
1057+
[case testNarrowingUsingMetaclass]
1058+
# flags: --strict-optional
1059+
from typing import Type
1060+
1061+
class M(type):
1062+
pass
1063+
1064+
class C: pass
1065+
1066+
def f(t: Type[C]) -> None:
1067+
if type(t) is M:
1068+
reveal_type(t) # N: Revealed type is "Type[__main__.C]"
1069+
else:
1070+
reveal_type(t) # N: Revealed type is "Type[__main__.C]"
1071+
if type(t) is not M:
1072+
reveal_type(t) # N: Revealed type is "Type[__main__.C]"
1073+
else:
1074+
reveal_type(t) # N: Revealed type is "Type[__main__.C]"
1075+
reveal_type(t) # N: Revealed type is "Type[__main__.C]"

0 commit comments

Comments
 (0)