diff --git a/mypy/constraints.py b/mypy/constraints.py index a078eb0b08b5..91e602f87ef6 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -172,6 +172,11 @@ def infer_constraints_if_possible(template: Type, actual: Type, if (direction == SUPERTYPE_OF and not mypy.subtypes.is_subtype(actual, erase_typevars(template))): return None + if (direction == SUPERTYPE_OF and isinstance(template, TypeVarType) and + not mypy.subtypes.is_subtype(actual, erase_typevars(template.upper_bound))): + # This is not caught by the above branch because of the erase_typevars() call, + # that would return 'Any' for a type variable. + return None return infer_constraints(template, actual, direction) diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 4dcbf411a779..22b1029ac805 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -2761,3 +2761,39 @@ def f() -> None: class C: def __init__(self, a: int) -> None: self.a = a + +[case testUnionGenericWithBoundedVariable] +from typing import Generic, TypeVar, Union + +T = TypeVar('T', bound=A) +class Z(Generic[T]): + def __init__(self, y: T) -> None: + self.y = y + +class A: ... +class B(A): ... +F = TypeVar('F', bound=A) + +def q1(x: Union[F, Z[F]]) -> F: + if isinstance(x, Z): + return x.y + else: + return x + +def q2(x: Union[Z[F], F]) -> F: + if isinstance(x, Z): + return x.y + else: + return x + +b: B +reveal_type(q1(b)) # N: Revealed type is '__main__.B*' +reveal_type(q2(b)) # N: Revealed type is '__main__.B*' + +z: Z[B] +reveal_type(q1(z)) # N: Revealed type is '__main__.B*' +reveal_type(q2(z)) # N: Revealed type is '__main__.B*' + +reveal_type(q1(Z(b))) # N: Revealed type is '__main__.B*' +reveal_type(q2(Z(b))) # N: Revealed type is '__main__.B*' +[builtins fixtures/isinstancelist.pyi]