Skip to content

Commit

Permalink
Always re-process annotations refering to an alias on update (#13759)
Browse files Browse the repository at this point in the history
This should fix a crash discovered by `mypy_primer` in
#13516

The logic here is that when type aliases have placeholders they are
updated _in place_ (the node gets a new resolved target type). But this
means that some variables annotated with type aliases may not get stored
types, unless we defer targets where they are defined.

This didn't cause troubles before, because we waited for type alias to
be complete before putting it into symbol table. Now it is not possible,
we need to put something into symbol table for partially complete
aliases to support recursive aliases (similar to recursive classes).

Also, it was tricky to come up with a repro for this issue, because when
it happens, the variable gets a "silent" `Any` type, and only when it
appears in a dataclass, it causes a crash.
  • Loading branch information
ilevkivskyi authored Sep 29, 2022
1 parent ef22444 commit 0f4e0fb
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
1 change: 1 addition & 0 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3032,6 +3032,7 @@ def process_type_annotation(self, s: AssignmentStmt) -> None:
analyzed = self.anal_type(s.type, allow_tuple_literal=allow_tuple_literal)
# Don't store not ready types (including placeholders).
if analyzed is None or has_placeholder(analyzed):
self.defer(s)
return
s.type = analyzed
if (
Expand Down
20 changes: 20 additions & 0 deletions test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
Expand Up @@ -1913,3 +1913,23 @@ class MyDataclass:

takes_cp(MyDataclass)
[builtins fixtures/dataclasses.pyi]

[case testDataclassTypeAnnotationAliasUpdated]
# flags: --enable-recursive-aliases
import a
[file a.py]
from dataclasses import dataclass
from b import B

@dataclass
class D:
x: B

reveal_type(D) # N: Revealed type is "def (x: builtins.list[b.C]) -> a.D"
[file b.py]
from typing import List
import a
B = List[C]
class C(CC): ...
class CC: ...
[builtins fixtures/dataclasses.pyi]

0 comments on commit 0f4e0fb

Please sign in to comment.