Skip to content

Commit 5b73e2a

Browse files
authored
Tweak constraint inference against unions to exclude more unsatisfiable items (#7922)
Fixes #6417 Currently constraint inference against unions excludes trivially unsatisfiable items, but a corner case of a plain type variable was missing, so I add one.
1 parent 84126ab commit 5b73e2a

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

mypy/constraints.py

+5
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ def infer_constraints_if_possible(template: Type, actual: Type,
172172
if (direction == SUPERTYPE_OF and
173173
not mypy.subtypes.is_subtype(actual, erase_typevars(template))):
174174
return None
175+
if (direction == SUPERTYPE_OF and isinstance(template, TypeVarType) and
176+
not mypy.subtypes.is_subtype(actual, erase_typevars(template.upper_bound))):
177+
# This is not caught by the above branch because of the erase_typevars() call,
178+
# that would return 'Any' for a type variable.
179+
return None
175180
return infer_constraints(template, actual, direction)
176181

177182

test-data/unit/check-inference.test

+36
Original file line numberDiff line numberDiff line change
@@ -2761,3 +2761,39 @@ def f() -> None:
27612761
class C:
27622762
def __init__(self, a: int) -> None:
27632763
self.a = a
2764+
2765+
[case testUnionGenericWithBoundedVariable]
2766+
from typing import Generic, TypeVar, Union
2767+
2768+
T = TypeVar('T', bound=A)
2769+
class Z(Generic[T]):
2770+
def __init__(self, y: T) -> None:
2771+
self.y = y
2772+
2773+
class A: ...
2774+
class B(A): ...
2775+
F = TypeVar('F', bound=A)
2776+
2777+
def q1(x: Union[F, Z[F]]) -> F:
2778+
if isinstance(x, Z):
2779+
return x.y
2780+
else:
2781+
return x
2782+
2783+
def q2(x: Union[Z[F], F]) -> F:
2784+
if isinstance(x, Z):
2785+
return x.y
2786+
else:
2787+
return x
2788+
2789+
b: B
2790+
reveal_type(q1(b)) # N: Revealed type is '__main__.B*'
2791+
reveal_type(q2(b)) # N: Revealed type is '__main__.B*'
2792+
2793+
z: Z[B]
2794+
reveal_type(q1(z)) # N: Revealed type is '__main__.B*'
2795+
reveal_type(q2(z)) # N: Revealed type is '__main__.B*'
2796+
2797+
reveal_type(q1(Z(b))) # N: Revealed type is '__main__.B*'
2798+
reveal_type(q2(Z(b))) # N: Revealed type is '__main__.B*'
2799+
[builtins fixtures/isinstancelist.pyi]

0 commit comments

Comments
 (0)