Skip to content

Restore transitive imports for cached modules#2677

Merged
plajjan merged 2 commits intomainfrom
fix-transitive-import
Mar 7, 2026
Merged

Restore transitive imports for cached modules#2677
plajjan merged 2 commits intomainfrom
fix-transitive-import

Conversation

@plajjan
Copy link
Contributor

@plajjan plajjan commented Mar 7, 2026

A module's direct imports are discovered in Compile from source or .ty headers and used to build import dependencies for scheduling. That is not the same thing as the full import closure needed by kinds and type checking. The actual import closure is reconstructed later in Env.mkEnv/doImp from the imported module's .ty files as we materialize the active environment for the module currently being compiled.

That distinction broke down once a direct import was already present in the shared modules env. doImp treated that as a full cache hit and returned immediately, which meant we never revisited the imported module's recorded imports. In practice the scheduler could have a cached interface for b while the active env still lacked a transitive import such as logging that b's public interface referred to. Reusing b.ty then failed later during type checking of a dependent module with "Module logging does not exist".

This change keeps the fast path for cached direct modules but still reads their .ty header imports and restores the recorded transitive import closure before returning. A visited set avoids looping while chasing the same module graph through cached hits and cold loads.

A regression test was added to incremental compiler tests for a small project where b imports logging and main imports only b while using a type from b that mentions logging. The second build now succeeds when b is reused from cached .ty state.

A new developer-guide note documents the split between scheduler discovery and environment materialization, the different env layers, and where .ty headers versus full .ty files are used. Nearby compiler pages now link to that note.

A module's direct imports are discovered in Compile from source or .ty
headers and used to build import dependencies for scheduling. That is
not the same thing as the full import closure needed by kinds and type
checking. The actual import closure is reconstructed later in
Env.mkEnv/doImp from the imported module's .ty files as we materialize
the active environment for the module currently being compiled.

That distinction broke down once a direct import was already present in
the shared modules env. doImp treated that as a full cache hit and
returned immediately, which meant we never revisited the imported
module's recorded imports. In practice the scheduler could have a cached
interface for b while the active env still lacked a transitive import
such as logging that b's public interface referred to. Reusing b.ty then
failed later during type checking of a dependent module with "Module
logging does not exist".

This change keeps the fast path for cached direct modules but still
reads their .ty header imports and restores the recorded transitive
import closure before returning. A visited set avoids looping while
chasing the same module graph through cached hits and cold loads.

A regression test was added to incremental compiler tests for a small
project where b imports logging and main imports only b while using a
type from b that mentions logging. The second build now succeeds when b
is reused from cached .ty state.

A new developer-guide note documents the split between scheduler
discovery and environment materialization, the different env layers, and
where .ty headers versus full .ty files are used. Nearby compiler pages
now link to that note.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9447edda3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Thread the updated seen set through subImpSeen so overlapping import
subgraphs are only walked once per reconstruction pass.
@plajjan plajjan enabled auto-merge March 7, 2026 09:56
@plajjan plajjan merged commit a3a2413 into main Mar 7, 2026
42 of 45 checks passed
@plajjan plajjan deleted the fix-transitive-import branch March 7, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant