Skip to content

Commit be46935

Browse files
authored
Make type variable upper bound narrowing symmetric (#21350)
Fixes #21199 Fixes #4952 This is kind of a simple-minded fix. The typeops around this are somewhat incomplete, but the opposite direction has been around for couple releases, and I don't think anyone complained, so I propose to go with this unless there are better ideas.
1 parent a07812d commit be46935

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

mypy/meet.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
173173
return declared.copy_modified(
174174
upper_bound=narrow_declared_type(declared.upper_bound, original_narrowed)
175175
)
176+
elif (
177+
isinstance(narrowed, TypeVarType)
178+
and not has_type_vars(original_declared)
179+
and is_subtype(original_declared, narrowed.upper_bound)
180+
):
181+
# This branch is a mirror image of the above one.
182+
return narrowed.copy_modified(
183+
upper_bound=narrow_declared_type(original_declared, narrowed.upper_bound)
184+
)
176185
elif not is_overlapping_types(declared, narrowed):
177186
if state.strict_optional:
178187
return UninhabitedType()

test-data/unit/check-narrowing.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4113,3 +4113,25 @@ def stringify(value: A | B | C) -> str:
41134113
return value.name
41144114
return ""
41154115
[builtins fixtures/tuple.pyi]
4116+
4117+
[case testTypeVariableBoundNarrowingSymmetric]
4118+
from typing import TypeVar
4119+
4120+
class B: ...
4121+
class C(B):
4122+
x: int
4123+
4124+
H = TypeVar('H', bound=B)
4125+
4126+
def func(y: H) -> H:
4127+
x: C
4128+
assert x == y
4129+
reveal_type(x) # N: Revealed type is "H`-1"
4130+
reveal_type(y) # N: Revealed type is "H`-1"
4131+
reveal_type(x.x) # N: Revealed type is "builtins.int"
4132+
reveal_type(y.x) # N: Revealed type is "builtins.int"
4133+
if bool():
4134+
return x
4135+
else:
4136+
return y
4137+
[builtins fixtures/primitives.pyi]

0 commit comments

Comments
 (0)