Skip to content

Resolve TSP type queries in files that aren't open (#4235)#4235

Open
kinto0 wants to merge 1 commit into
facebook:mainfrom
kinto0:export-D113135763
Open

Resolve TSP type queries in files that aren't open (#4235)#4235
kinto0 wants to merge 1 commit into
facebook:mainfrom
kinto0:export-D113135763

Conversation

@kinto0

@kinto0 kinto0 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary:

TSP getComputedType (and getDeclaredType/getExpectedType) returned
null for any node in a file that wasn't open in the editor, even though
the file was on disk, reachable, and analyzed as a dependency of an open
file. Opening the same file made the identical (uri, range) query
succeed. This broke every node in Pyrefly's bundled stdlib stubs (e.g.
builtins.pyi), which clients like Pylance never didOpen.

Fixes #4228.

The root cause: computed_type_at_range and open_at_position built the
handle with make_open_handle, which always uses ModulePath::memory.
In-memory content only exists for opened files, so the memory-keyed handle
only matched open documents; closed files are keyed under FileSystem or
BundledTypeshed handles (whose SysInfo is inherited from the importer
and can't be reconstructed here), so the lookup missed and short-circuited
to null.

New helper query_transaction_and_handle resolves a path to the handle the
checker actually analyzes it under:

  • open files -> in-memory overlay (unchanged fast path);
  • otherwise reuse the already-loaded handle: the filesystem handle when it
    can be rebuilt directly, else a by-path scan that reuses the loaded
    BundledTypeshed handle so stdlib queries don't re-check typeshed;
  • fall back to a fresh filesystem handle read from disk when the file
    hasn't been analyzed yet.

It then forces a full solve at Require::Everything, the only level that
retains bindings/answers — exactly the data the type lookup reads — so the
result is available regardless of what require level the file was loaded
at as a dependency. Open-file queries are unchanged; only the previously
null closed-file path does additional work, and bundled typeshed reuses
its already-solved handle.

Differential Revision: D113135763

@meta-cla meta-cla Bot added the cla signed label Jul 21, 2026
@meta-codesync

meta-codesync Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@kinto0 has exported this pull request. If you are a Meta employee, you can view the originating Diff in D113135763.

Summary:

TSP `getComputedType` (and `getDeclaredType`/`getExpectedType`) returned
`null` for any node in a file that wasn't open in the editor, even though
the file was on disk, reachable, and analyzed as a dependency of an open
file. Opening the same file made the identical `(uri, range)` query
succeed. This broke every node in Pyrefly's bundled stdlib stubs (e.g.
`builtins.pyi`), which clients like Pylance never `didOpen`.

Fixes facebook#4228.

The root cause: `computed_type_at_range` and `open_at_position` built the
handle with `make_open_handle`, which always uses `ModulePath::memory`.
In-memory content only exists for opened files, so the memory-keyed handle
only matched open documents; closed files are keyed under `FileSystem` or
`BundledTypeshed` handles (whose `SysInfo` is inherited from the importer
and can't be reconstructed here), so the lookup missed and short-circuited
to `null`.

New helper `query_transaction_and_handle` resolves a path to the handle the
checker actually analyzes it under:
- open files -> in-memory overlay (unchanged fast path);
- otherwise reuse the already-loaded handle: the filesystem handle when it
  can be rebuilt directly, else a by-path scan that reuses the loaded
  `BundledTypeshed` handle so stdlib queries don't re-check typeshed;
- fall back to a fresh filesystem handle read from disk when the file
  hasn't been analyzed yet.

It then forces a full solve at `Require::Everything`, the only level that
retains bindings/answers — exactly the data the type lookup reads — so the
result is available regardless of what require level the file was loaded
at as a dependency. Open-file queries are unchanged; only the previously
`null` closed-file path does additional work, and bundled typeshed reuses
its already-solved handle.

Differential Revision: D113135763
@meta-codesync meta-codesync Bot changed the title Resolve TSP type queries in files that aren't open Resolve TSP type queries in files that aren't open (#4235) Jul 21, 2026
@kinto0
kinto0 force-pushed the export-D113135763 branch from 350ee71 to 4158781 Compare July 21, 2026 23:47
@github-actions github-actions Bot added size/m and removed size/m labels Jul 21, 2026
@github-actions

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@stroxler stroxler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TSP: getComputedType returns null for nodes in files that aren't open (open vs closed files resolve differently)

3 participants