Open Cnoor0171 opened 3 years ago
The inferred return type of the dict.get
function is also affected by this.
a_dict: dict[int, list[str]] = {}
list_of_ints: list[int] = [1,2,3]
reveal_type(a_dict.get(0, [1,2,3])) # Produces error. Revealed type is 'builtins.list[builtins.str]'
reveal_type(a_dict.get(0, 123)) # Works. Revealed type is 'Union[builtins.list[builtins.str], builtins.int*]'
reveal_type(a_dict.get(0, list_of_ints)) # Works. Revealed type is 'Union[builtins.list[builtins.str], builtins.list*[builtins.int]]'
gives
file.py:4: note: Revealed type is 'builtins.list[builtins.str]'
file.py:4: error: List item 0 has incompatible type "int"; expected "str"
file.py:4: error: List item 1 has incompatible type "int"; expected "str"
file.py:4: error: List item 2 has incompatible type "int"; expected "str"
file.py:5: note: Revealed type is 'Union[builtins.list[builtins.str], builtins.int*]'
file.py:6: note: Revealed type is 'Union[builtins.list[builtins.str], builtins.list*[builtins.int]]'
Found 3 errors in 1 file (checked 1 source file)
I suspect this is a bad interaction with list's invariance and mypy's type context.
For an example of where this is useful, see:
list_of_ints: list[int]
list_of_floats: list[float] = list_of_ints # error, due to list's invariance
list_of_floats_2: list[float] = [1,2,3] # passes, because mypy uses the type context of list[float] when inferring what type [1,2,3] is supposed to be, allowing it to conclude that [1,2,3] is list[float] and hence that the assignment is okay.
I'm not quite sure what definition of or
mypy is using when you get that error. The dict.get one is similar to https://github.com/python/typeshed/pull/5516#issuecomment-846275361
Like your example shows, aliasing is a workaround (and you don't even need to explicitly annotate it). Casting should also work.
Bug Report
When two lists whose elements have different types appear in an
or
expression, type inferencing doesn't work properly if the second list is a literal. If the second list is assigned to a variable first, the type inference works.For instance, if
my_str_list
is aList[str]
andmy_int_list
is aList[int]
, the expressionmy_str_list or my_int_list
has inferred typeUnion[List[str], List[int]]
, whilemy_str_list or [1, 2, 3]
has inferred typeList[str]
(accompanied by an error saying the elements of the literal list are the wrong type).To Reproduce
The following file:
gives output
Expected Behavior
Expected no error and
reveal_type(["a", "b"] or [1,2,3])
to beUnion[List[str], List[int]]
or evenList[int]
if mypy is able to determine that["a", "b"]
is a truthy value.Actual Behavior
reveal_type(["a", "b"] or [1,2,3])
isList[str]
and there is error claiming the types of the literal list are wrong.Your Environment
mypy.ini
(and other config files): None