Fix accessing qualified import in incremental mode #3548
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request fixes #3274
The problem was that mypy was previously doing the following, given an empty cache:
['c.d']
, then['c']
, then['b']
, then['a']
. No issues here.c.d
to cache -- also no issues here.c
to cache. The error occurs here -- mypy doesn't recognize thatc
has any submodules, and so will not recordc.d
intoc
's symbol table. This means the saved cache forc
will be essentially empty.b
, mypy will recognize thatc.d
is a submodule ofc
due to the import. During the semantic analysis phase (more precisely, inSemanticAnalyzer.add_submodules_to_parent_modules
), mypy will actually modifyc
's symbol table to included
, which is why typechecking succeeds forb
anda
during a fresh run. However, this change wasn't ever written to the cache, so won't be remembered when re-running incremental mode!a
, using the modified (but not preserved) symbol table.Or to put it more succinctly, the code sometimes seems to be relying on the assumption that a symbol table for a given module will not be modified after that SCC is processed. However, this invariant is false due to the 'parent patching' mechanism.
This commit opts for a relatively conservative course of action by simply re-running this patching process when handling fresh SCCs.
Other potential fixes I considered included deferring writing to cache until all SCCs are processed to try and preserve this info and restore the above invariant (which initially seemed like a more robust solution but broke multiple tests when I tried it), or replacing the current parent patching mechanism with something entirely different (which seems like the sort of thing that could subtly break code).