Skip to content

Commit d6296de

Browse files
committed
Narrow type with typevar when the lower bound of its upper bound and that type is same
1 parent d3c30fe commit d6296de

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
@@ -7,6 +7,7 @@
77
UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType,
88
ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardType
99
)
10+
from mypy.sametypes import is_same_type
1011
from mypy.subtypes import is_equivalent, is_subtype, is_callable_compatible, is_proper_subtype
1112
from mypy.erasetype import erase_type
1213
from mypy.maptype import map_instance_to_supertype
@@ -77,6 +78,10 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
7778
and narrowed.type.is_metaclass()):
7879
# We'd need intersection types, so give up.
7980
return declared
81+
elif isinstance(narrowed, TypeVarType):
82+
if is_same_type(narrowed.upper_bound, meet_types(narrowed.upper_bound, declared)):
83+
return narrowed
84+
return meet_types(declared, narrowed)
8085
elif isinstance(declared, (Instance, TupleType, TypeType, LiteralType)):
8186
return meet_types(declared, narrowed)
8287
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
@@ -1073,3 +1073,23 @@ def f(t: Type[C]) -> None:
10731073
else:
10741074
reveal_type(t) # N: Revealed type is "Type[__main__.C]"
10751075
reveal_type(t) # N: Revealed type is "Type[__main__.C]"
1076+
1077+
[case testNarrowingUsingTypeVar]
1078+
# flags: --strict-optional
1079+
from typing import Type, TypeVar
1080+
1081+
class A: pass
1082+
class B(A): pass
1083+
1084+
T = TypeVar("T", bound=A)
1085+
1086+
def f(t: Type[T], a: A, b: B) -> None:
1087+
if type(a) is t:
1088+
reveal_type(a) # N: Revealed type is "T`-1"
1089+
else:
1090+
reveal_type(a) # N: Revealed type is "__main__.A"
1091+
1092+
if type(b) is t:
1093+
reveal_type(b) # N: Revealed type is "<nothing>"
1094+
else:
1095+
reveal_type(b) # N: Revealed type is "__main__.B"

0 commit comments

Comments
 (0)