python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.31k stars 2.81k forks source link

Need type annotation for predefined dict generic (3.9) #11093

Open ultrabear opened 3 years ago

ultrabear commented 3 years ago

Bug Report mypy errors on defining a variable to a python 3.9 dict whose type signature has been previously stored in a variable

To Reproduce Using mypy bug.py --strict Error stems from disallow untyped generics, I think

Block = dict[str, str]

def main() -> Block:

    out = Block()  # error: Need type annotation for "out" (hint: "out: Dict[<type>, <type>] = ...")

    return out

if __name__ == "__main__":
    main()

Expected Behavior

Mypy should be able to read the type information stored in Block and read it as that type being init, as it can read the type information for a return signature

Actual Behavior mypy raises a untyped generic error that out needs a type annotation: error: Need type annotation for "out" (hint: "out: Dict[<type>, <type>] = ...")

Your Environment

hi-ogawa commented 3 years ago

EDIT: Actually var-annotated error code is enabled by default (i.e. without --strict option).

I'm starting to take a look at this issue and I made an example of my own. Interestingly, there doesn't seem a problem for list.

from typing import Dict, List

D1 = dict[str, str]
D2 = Dict[str, str]
x1 = D1()
x2 = D2()
x3 = dict[str, str]()

L1 = list[str]
L2 = List[str]
y1 = L1()
y2 = L2()
y3 = list[str]()
$ mypy --show-error-codes ex11093/test3.py 
ex11093/test3.py:5: error: Need type annotation for "x1" (hint: "x1: Dict[<type>, <type>] = ...")  [var-annotated]
ex11093/test3.py:6: error: Need type annotation for "x2" (hint: "x2: Dict[<type>, <type>] = ...")  [var-annotated]
Found 2 errors in 1 file (checked 1 source file)

UPDATE (1): This issue might be partially due to SemanticAnalyzer.translate_dict_call where this kind of translation doesn't happen for list builtin. https://github.com/python/mypy/blob/492739692206f05347c6706cb982115446ba552a/mypy/semanal.py#L3813

Not sure yet but this translation is to support TypedDict construction like this? I commented out translate_dict_call and the first test failure I got is this. https://github.com/python/mypy/blob/492739692206f05347c6706cb982115446ba552a/test-data/unit/check-typeddict.test#L14-L17

Looking at PEP589, it seems it actually doesn't allow such construction of TypedDict https://github.com/python/peps/blob/master/pep-0589.rst?plain=1#L210-L212

It can be used as a callable object with keyword arguments corresponding to the TypedDict items. Non-keyword arguments are not allowed.


UPDATE (2): The reason why Dict[str, str]() works is that such expression actually won't get translated by translate_dict_call due to its AST:

CallExpr:2(
  TypeApplication:2(
    NameExpr(Dict [typing.Dict])
    Types(
      builtins.str
      builtins.str))
  Args())
AlexWaygood commented 2 years ago

I've removed the "topic-585" label as I can reproduce this with typing.Dict as well as builtins.dict

vsego commented 3 weeks ago

Two years later, and this is still an issue:

from typing import TypeAlias

T_foo: TypeAlias = dict[str, int]

foo = T_foo()

Any progress with it?