mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Argument type `Union[T, List[T]]` fails to infer constaints

Open sobolevn opened this issue 4 years ago β€’ 2 comments

While working on #11128 I got hit by this.

This code does not type check:

from typing import TypeVar, Union, List

T1 = TypeVar("T1")

def promote_list(item: Union[T1, List[T1]]) -> List[T1]:
    ...

exprs: List[int]
reveal_type(promote_list(exprs))  # error
# ex.py:9: note: Revealed type is "builtins.list[<nothing>]"
# ex.py:9: error: Argument 1 to "promote_list" has incompatible type "List[int]"; expected "List[<nothing>]"

reveal_type(promote_list(1))  # ok
# Revealed type is "builtins.list[builtins.int*]"

Which is not what I expect. For example, TypeScript solves this properly:

function protomoteList<T>(input: T | T[]): T[] {
    return []
}

function test(input: number[]) {}

test(protomoteList(1))  # ok

Link: https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABABwE5ynAthgpgGRgGcoAeAFQD4AKGMZEKALkXMQB9WBtAXQEoW5XogDeAWABQiaYlS4oIVEl6SAvpMmhIsBIii4SteoxZgQWAEa5UvPqPUTJ+w2gzY8hQwEY+fSUA

Cause

It happens somewhere here: https://github.com/python/mypy/blob/b3ff2a683bd41a176c597d3c3ba65f6a31f805c5/mypy/constraints.py#L168-L171

I will try to solve this, but I know that this is going to be complicated.

sobolevn avatar Sep 20 '21 14:09 sobolevn

β˜ οΈπŸ‘ΏπŸ§Ÿβ€β™€οΈπŸ’ƒπŸ€«

Thanayaby avatar Nov 20 '21 18:11 Thanayaby

Adding an upper bound on T1 fixes this, see https://github.com/python/mypy/issues/6417. Although I agree it would be great if this worked without a bound. Proper solution for this is complex however.

ilevkivskyi avatar Aug 05 '22 11:08 ilevkivskyi