From 98886867e1cdfb0912c03f065f0cf4d5095c30bd Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 21 Feb 2022 17:06:16 +0000 Subject: [PATCH] Use type variable bound to infer constraints This fixes a regression where `iter(x)` could generate a false positive if `x` has a type variable type. --- mypy/constraints.py | 4 ++++ test-data/unit/check-protocols.test | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/mypy/constraints.py b/mypy/constraints.py index 9bc233054e91..2835840f8375 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -513,6 +513,10 @@ def visit_instance(self, template: Instance) -> List[Constraint]: return infer_constraints(template, mypy.typeops.tuple_fallback(actual), self.direction) + elif isinstance(actual, TypeVarType): + if not actual.values: + return infer_constraints(template, actual.upper_bound, self.direction) + return [] else: return [] diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index a5962bde5333..fa1ac56c11b9 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -2806,3 +2806,24 @@ class MyClass: assert isinstance(self, MyProtocol) [builtins fixtures/isinstance.pyi] [typing fixtures/typing-full.pyi] + +[case testProtocolAndTypeVariableSpecialCase] +from typing import TypeVar, Iterable, Optional, Callable, Protocol + +T_co = TypeVar('T_co', covariant=True) + +class SupportsNext(Protocol[T_co]): + def __next__(self) -> T_co: ... + +N = TypeVar("N", bound=SupportsNext, covariant=True) + +class SupportsIter(Protocol[T_co]): + def __iter__(self) -> T_co: ... + +def f(i: SupportsIter[N]) -> N: ... + +I = TypeVar('I', bound=Iterable) + +def g(x: I, y: Iterable) -> None: + f(x) + f(y)