From d9c29490e3187f0d6d3bf588edc6f2dd8fe3314a Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 10 Jun 2026 13:46:06 +0100 Subject: [PATCH 1/5] Support --shadow-file with --native-parser --- mypy/build.py | 4 +++- test-data/unit/cmdline.test | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/mypy/build.py b/mypy/build.py index 97db8fe1646cd..7fc9526ccb2fe 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/cmdline.test b/test-data/unit/cmdline.test index cfba7a81e9285..60b42d115284f 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 --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] From ca61e28a3aa20a4e88de795b0d6b09fae63e5a95 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 19 Jun 2026 10:36:11 +0100 Subject: [PATCH 2/5] Use --num-workers in test --- test-data/unit/cmdline.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 60b42d115284f..7066034b3e39c 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -543,7 +543,7 @@ source.py:2: note: Revealed type is "str" == Return code: 0 [case testShadowFileWithNativeParserParallel] -# cmd: mypy --native-parser --shadow-file a.py a_shadow.py main.py a.py b.py +# 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 From 37e393ef2a1b3b5df0dadff03361d72ef83bfd9a Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 19 Jun 2026 12:52:37 +0100 Subject: [PATCH 3/5] Add incremental tests --- test-data/unit/check-incremental.test | 97 +++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 9647393cdac66..cf230cd1a2e12 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -8139,3 +8139,100 @@ 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 +[file a.py] +import c +x: int = 1 +reveal_type(x) +[file b.py] +y: int = 2 +[file c.py] +z: int = 3 +[file a_shadow.py] +import c +x: str = "y" +reveal_type(x) +[rechecked] +[stale] +[out1] +tmp/a.py:3: note: Revealed type is "builtins.str" +[out2] +tmp/a.py:3: note: Revealed type is "builtins.str" + +[case testIncrementalNativeParserShadowFileParallel] +# flags: --native-parser --num-workers=2 --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 +reveal_type(y) +[file a_shadow.py] +x: str = "y" +reveal_type(x) +[rechecked] +[stale] +[out1] +tmp/a.py:2: note: Revealed type is "builtins.str" +tmp/b.py:2: note: Revealed type is "builtins.int" +[out2] +tmp/a.py:2: note: Revealed type is "builtins.str" +tmp/b.py:2: note: Revealed type is "builtins.int" + +[case testIncrementalNativeParserShadowFileChanged] +# flags: --native-parser --num-workers=2 --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 +reveal_type(y) +[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" +tmp/b.py:2: note: Revealed type is "builtins.int" +[out2] +tmp/a.py:2: note: Revealed type is "builtins.bytes" +tmp/b.py:2: note: Revealed type is "builtins.int" + +[case testIncrementalNativeParserShadowFileIntroduced] +# flags: --native-parser --num-workers=2 +# flags2: --native-parser --num-workers=2 --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 +reveal_type(y) +[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" +tmp/b.py:2: note: Revealed type is "builtins.int" +[out2] +tmp/a.py:2: note: Revealed type is "builtins.str" +tmp/b.py:2: note: Revealed type is "builtins.int" From 77701d1f45f5dcf5784cf8b7c7c9291ed84fa284 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 19 Jun 2026 13:41:58 +0100 Subject: [PATCH 4/5] Simplify tests, all of these are run in parallel as well --- test-data/unit/check-incremental.test | 29 +++------------------------ 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index cf230cd1a2e12..4a1b31740ab87 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -8144,29 +8144,6 @@ tmp/b.py:2: note: Revealed type is "builtins.int" # flags: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py import a import b -[file a.py] -import c -x: int = 1 -reveal_type(x) -[file b.py] -y: int = 2 -[file c.py] -z: int = 3 -[file a_shadow.py] -import c -x: str = "y" -reveal_type(x) -[rechecked] -[stale] -[out1] -tmp/a.py:3: note: Revealed type is "builtins.str" -[out2] -tmp/a.py:3: note: Revealed type is "builtins.str" - -[case testIncrementalNativeParserShadowFileParallel] -# flags: --native-parser --num-workers=2 --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 @@ -8187,7 +8164,7 @@ tmp/a.py:2: note: Revealed type is "builtins.str" tmp/b.py:2: note: Revealed type is "builtins.int" [case testIncrementalNativeParserShadowFileChanged] -# flags: --native-parser --num-workers=2 --shadow-file tmp/a.py tmp/a_shadow.py +# 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. @@ -8213,8 +8190,8 @@ tmp/a.py:2: note: Revealed type is "builtins.bytes" tmp/b.py:2: note: Revealed type is "builtins.int" [case testIncrementalNativeParserShadowFileIntroduced] -# flags: --native-parser --num-workers=2 -# flags2: --native-parser --num-workers=2 --shadow-file tmp/a.py tmp/a_shadow.py +# 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. From 25a1ad6480d36186f07e0f621a49ecdf3b24025b Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 19 Jun 2026 15:09:00 +0100 Subject: [PATCH 5/5] Try to fix test flakiness --- test-data/unit/check-incremental.test | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 4a1b31740ab87..7ff9fbef06a53 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -8150,7 +8150,6 @@ x: int = 1 reveal_type(x) [file b.py] y: int = 2 -reveal_type(y) [file a_shadow.py] x: str = "y" reveal_type(x) @@ -8158,10 +8157,8 @@ reveal_type(x) [stale] [out1] tmp/a.py:2: note: Revealed type is "builtins.str" -tmp/b.py:2: note: Revealed type is "builtins.int" [out2] tmp/a.py:2: note: Revealed type is "builtins.str" -tmp/b.py:2: note: Revealed type is "builtins.int" [case testIncrementalNativeParserShadowFileChanged] # flags: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py @@ -8173,7 +8170,6 @@ x: int = 1 reveal_type(x) [file b.py] y: int = 2 -reveal_type(y) [file a_shadow.py] x: str = "y" reveal_type(x) @@ -8184,10 +8180,8 @@ reveal_type(x) [stale a] [out1] tmp/a.py:2: note: Revealed type is "builtins.str" -tmp/b.py:2: note: Revealed type is "builtins.int" [out2] tmp/a.py:2: note: Revealed type is "builtins.bytes" -tmp/b.py:2: note: Revealed type is "builtins.int" [case testIncrementalNativeParserShadowFileIntroduced] # flags: --native-parser @@ -8201,7 +8195,6 @@ x: int = 1 reveal_type(x) [file b.py] y: int = 2 -reveal_type(y) [file a_shadow.py.2] x: str = "y" reveal_type(x) @@ -8209,7 +8202,5 @@ reveal_type(x) [stale a] [out1] tmp/a.py:2: note: Revealed type is "builtins.int" -tmp/b.py:2: note: Revealed type is "builtins.int" [out2] tmp/a.py:2: note: Revealed type is "builtins.str" -tmp/b.py:2: note: Revealed type is "builtins.int"