Отрицательное сужение типа объединения с TypeIs TypeVar не работает должным образом в новой версии mypy.Python

Программы на Python
Ответить
Anonymous
 Отрицательное сужение типа объединения с TypeIs TypeVar не работает должным образом в новой версии mypy.

Сообщение Anonymous »

Недавно я обновил mypy с 1.17.0 до 1.18.2
Следующий код был успешно проверен в старой версии mypy (1.17.0), но не выполнен в новой (1.18.2):

Код: Выделить всё

_T = TypeVar('_T')

class Foo(Generic[_T], ABC):
pass

def to_foo(value: _T | Foo[_T],
checker: Callable[[Any], TypeIs[_T]],
factory: Callable[[_T], Foo[_T]]) -> Foo[_T]:
if checker(value):
return factory(value)
else:
return value
Это ошибка:

Код: Выделить всё

error: Incompatible return value type (got "_T | Foo[_T]", expected "Foo[_T]")  [return-value]
Mypy, похоже, недоволен вторым оператором возврата. Кажется, он не может сделать вывод, что если значение равно _T | Foo[_T] для начала, а не _T (в другом случае), он должен иметь тип Foo[_T].
Хотя я думал, что это именно то, что делает TypeIs:

Сужение типа применяется как в положительном, так и в отрицательном случае

Когда я уменьшаю проблему далее я получаю следующую функцию, которая по-прежнему не работает:

Код: Выделить всё

_T = TypeVar('_T')

def mypy_fails(x: _T | int, checker: Callable[[Any], TypeIs[_T]], default: int) -> int:
if checker(x):
return default
else:
return x
Похоже, это связано с TypeVar, поскольку следующая функция (с переключенными int и _T) все еще проверяет:

Код: Выделить всё

def mypy_validates(x: int | _T, checker: Callable[[Any], TypeIs[int]], default: _T) -> _T:
if checker(x):
return default
else:
return x
Что не так с моим исходным кодом? Почему mypy_validates работает? И почему в старой версии mypy всё было нормально, а в новой нет?

Подробнее здесь: https://stackoverflow.com/questions/798 ... s-expected
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»