diff --git a/mypy/build.py b/mypy/build.py index 97db8fe1646c..7fc9526ccb2f 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -1030,7 +1030,9 @@ def parse_all(self, states: list[State], post_parse: bool = True) -> None: parallel_states = [] for state in states: - if not self.fscache.exists(state.xpath, real_only=True): + if not self.fscache.exists(state.xpath, real_only=True) or ( + self.shadow_map and self.maybe_swap_for_shadow_path(state.xpath) != state.xpath + ): state.source = state.get_source() if state.tree is not None: # The file was already parsed. diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 9647393cdac6..7ff9fbef06a5 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -8139,3 +8139,68 @@ reveal_type(test("int")) [out] [out2] tmp/b.py:2: note: Revealed type is "builtins.int" + +[case testIncrementalNativeParserShadowFile] +# flags: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py +import a +import b +-- a and b don't depend on each other, so they can be checked in parallel. +[file a.py] +x: int = 1 +reveal_type(x) +[file b.py] +y: int = 2 +[file a_shadow.py] +x: str = "y" +reveal_type(x) +[rechecked] +[stale] +[out1] +tmp/a.py:2: note: Revealed type is "builtins.str" +[out2] +tmp/a.py:2: note: Revealed type is "builtins.str" + +[case testIncrementalNativeParserShadowFileChanged] +# flags: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py +import a +import b +-- a and b don't depend on each other, so they can be checked in parallel. +[file a.py] +x: int = 1 +reveal_type(x) +[file b.py] +y: int = 2 +[file a_shadow.py] +x: str = "y" +reveal_type(x) +[file a_shadow.py.2] +x: bytes = b"y" +reveal_type(x) +[rechecked a] +[stale a] +[out1] +tmp/a.py:2: note: Revealed type is "builtins.str" +[out2] +tmp/a.py:2: note: Revealed type is "builtins.bytes" + +[case testIncrementalNativeParserShadowFileIntroduced] +# flags: --native-parser +# flags2: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py +import a +import b +-- a and b don't depend on each other, so they can be checked in parallel. +-- The first run has no shadow file; the second run introduces one for a.py. +[file a.py] +x: int = 1 +reveal_type(x) +[file b.py] +y: int = 2 +[file a_shadow.py.2] +x: str = "y" +reveal_type(x) +[rechecked a] +[stale a] +[out1] +tmp/a.py:2: note: Revealed type is "builtins.int" +[out2] +tmp/a.py:2: note: Revealed type is "builtins.str" diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index cfba7a81e928..7066034b3e39 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -530,6 +530,35 @@ variable has type "bytes") b: bytes = 1 ^ +[case testShadowFileWithNativeParser] +# cmd: mypy --native-parser --shadow-file source.py shadow.py source.py +[file source.py] +x: int = 1 +reveal_type(x) +[file shadow.py] +x: str = "y" +reveal_type(x) +[out] +source.py:2: note: Revealed type is "str" +== Return code: 0 + +[case testShadowFileWithNativeParserParallel] +# cmd: mypy --native-parser --num-workers=4 --shadow-file a.py a_shadow.py main.py a.py b.py +[file main.py] +import a +import b +[file a.py] +x: int = 1 +reveal_type(x) +[file b.py] +y: int = 2 +[file a_shadow.py] +x: str = "y" +reveal_type(x) +[out] +a.py:2: note: Revealed type is "str" +== Return code: 0 + [case testConfigWarnUnusedSection1] # cmd: mypy foo.py quux.py spam/eggs.py [file mypy.ini]