Commit ef4d492
committed
Stop TypedDictAnalyzer from leaking synthetic types
Fixes #10007
Mypy currently crashes when you try:
1. Creating a class-based TypedDict containing a malformed type hint
2. Asking it to compute fine-grained dependencies, either via
running dmypy or by setting the `--cache-fine-grained` flag.
Here is the exact sequence of events that leads to this crash:
1. Since the type annotation is malformed, semanal initially gives
the type annotation a type of `RawExpressionType`.
2. TypedDictAnalyzer (correctly) determines determines that the
type of the malformed type annotation should be treated as
just `Any` in:
https://github.com/python/mypy/blob/f5ce4ee6ca7e2d8bb1cde8a2b49865f53bbacff5/mypy/semanal_typeddict.py#L289
3. TypedDictAnalyzer forgets to modify `stmt.type` like we normally
do after calling `self.anal_type` in normal classes:
https://github.com/python/mypy/blob/f5ce4ee6ca7e2d8bb1cde8a2b49865f53bbacff5/mypy/semanal.py#L3022
4. Mypy _does_ use the `Any` type when constructing the TypeInfo
for the TypedDict. This is why mypy will not crash under most
conditions: the correct type is being used in most places.
5. Setting `--cache-fine-grained` will make mypy perform one final
pass against the AST to compute fine-grained dependencies. As
a part of this process, it traverses the AssigmentStatement's `type`
field using TypeTriggersVisitor.
6. TypeTriggersVisitor is _not_ a SyntheticTypeVisitor. So, the
visitor trips an assert when we try traversing into the
RawExpressionType.
Interestingly, this same crash does not occur for NamedTuples
despite the fact that NamedTupleAnalyzer also does not set `stmt.type`:
https://github.com/python/mypy/blob/f5ce4ee6ca7e2d8bb1cde8a2b49865f53bbacff5/mypy/semanal_namedtuple.py#L177
It turns out this is because semanal.py will end up calling the
`analyze_class_body_common(...)` function after NamedTupleAnalyzer
runs, but _not_ after TypedDictAnalyzer runs:
- https://github.com/python/mypy/blob/f5ce4ee6ca7e2d8bb1cde8a2b49865f53bbacff5/mypy/semanal.py#L1510
- https://github.com/python/mypy/blob/f5ce4ee6ca7e2d8bb1cde8a2b49865f53bbacff5/mypy/semanal.py#L1479
I'm not sure why this is: ideally, the two analyzers ought to have
as similar semantics as possible. But refactoring this felt potentially
disruptive, so I went for the narrower route of just patching TypedDictAnalyzer.1 parent cf705d7 commit ef4d492
File tree
3 files changed
+37
-1
lines changed- mypy
- test-data/unit
3 files changed
+37
-1
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
294 | 294 | | |
295 | 295 | | |
296 | 296 | | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
297 | 303 | | |
298 | 304 | | |
299 | 305 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
| 45 | + | |
0 commit comments