Sometime we want to use a class in typing before the class itself is defined, in such cases we can use quotes. Suppose we have a type alias B depending on class A and a class A which (in my code, not in this simplified example) uses B. With mypy 1.17, the following code:
type B[T:"A"] = int
class A:
pass
produces as mypy output:
$ mypy test.py
Traceback (most recent call last):
File "/home/janr/local/anaconda3/envs/trumpet/bin/mypy", line 7, in <module>
sys.exit(console_entry())
^^^^^^^^^^^^^^^
File "/home/janr/local/anaconda3/envs/trumpet/lib/python3.12/site-packages/mypy/__main__.py", line 15, in console_entry
main()
File "mypy/main.py", line 127, in main
File "mypy/main.py", line 211, in run_build
File "mypy/build.py", line 191, in build
File "mypy/build.py", line 267, in _build
File "mypy/build.py", line 2939, in dispatch
File "mypy/build.py", line 3337, in process_graph
File "mypy/build.py", line 3464, in process_stale_scc
File "mypy/build.py", line 2501, in write_cache
File "mypy/build.py", line 1562, in write_cache
File "mypy/nodes.py", line 367, in serialize
File "mypy/nodes.py", line 4138, in serialize
File "mypy/nodes.py", line 4074, in serialize
File "mypy/nodes.py", line 3806, in serialize
File "mypy/types.py", line 696, in serialize
File "mypy/types.py", line 3191, in serialize
AssertionError: Internal error: unresolved placeholder type None
which is not really what I expect. Maybe my code is illegal, but then maybe mypy should produce a comprehensive error message.
In this minimal example, if I put the definition of class A before the definition of B, mypy runs smoothly (not reporting any errors). (In my own code, I can’t do that because the definition of class A depends on type alias B).
Also, the problem may disappear in different but similar cases:
type B[T:"A"] = "C"
class A:
pass
class C:
pass
Mypy runs and doesn’t find errors in this code.
I understand it may be wasteful to define an alias depending on class A (as bound for T) but not using A or T inside the body of its definition, but the documentation doesn’t seem to forbid it (and my last example using “C” doesn’t let the body of the definition of “B” use “A” either). My intention was to later extend the definition of B with something depending on A and to have the parameter T already in the code.
Is this a mypy bug or do I misunderstand what I’m allowed to do with aliases/parameters (or both) ?