Skip to content

Only materialize reachable code for back passes - #3039

Draft
plajjan wants to merge 9 commits into
mainfrom
selective-back
Draft

Only materialize reachable code for back passes#3039
plajjan wants to merge 9 commits into
mainfrom
selective-back

Conversation

@plajjan

@plajjan plajjan commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Front passes run on 100% of a module. This changes so that for back passes, we only load and process names that are reachable.

Reachability facts are stored as exact TYDB rows and selected interfaces are reconstructed on demand. Rootless modules stop after front-pass persistence, while executable builds generate consumer-specific provider projections.

The project selection can be inspected with acton sig --reachability. Module and exact-name targets show the cached reachability facts stored in a TYDB.

The synchronous output path still checked generation eligibility after
announcing that a write had started. An implementation refresh could
also commit its rows before forcing the restored module values used by
the following back pass.

Decide synchronous-write eligibility once, then always finish the
announced action and report its timing. Force restored module values
before the refreshed transaction commits, so front completion remains a
single reliable boundary for every later row reader.
@plajjan plajjan changed the title Compile deferred modules selectively Only materialize reachable code for back passes Jul 24, 2026
Kristian Larsson added 7 commits July 25, 2026 09:17
Split inferred modules into validated top, member,
constructor-fragment, and compact-header rows that preserve source order
and lowering semantics.

Expose the type checker's constructor analysis as the canonical
boundary for attribute initialization, and share actor-state
classification with Deactorizer. This lets later projections restore
only the declarations and initialization fragments they need.
Derive witness-forwarding plans before code generation and walk inferred
modules with their type environments to record exact top-level, member,
constructor, provider, shape, and reflection obligations.

Store typed rows, reachability, hash inputs, and generation identity in
one interface snapshot. Resolve aliases while classifying receivers,
record Normalizer's truth conversions, and retain inherited property
declarations needed to keep whole and selective layouts identical.

Missing or impossible typed targets remain compiler errors; selection
never widens to wildcard interest. Bump the interface version so caches
written without these rows are rebuilt.
Close typed reachability with an exact-key, order-independent worklist,
including inherited providers, constructors, witness dictionaries,
reflection, fields, initializer fragments, and generated slots.

Restore only selected rows from one interface snapshot and assemble a
coherent module and environment for the existing back pipeline. Missing,
ambiguous or generation-shifted rows are errors rather than reasons to
widen the projection.
Plan whole and projected provider work separately, run projections
against their captured interface generation, and serialize generated
output by destination across the CLI, language server, tests, and
benchmarks.

Keep one generation-bound read session per projection and query only the
public names, headers, bodies, reachability rows, and opaque hashes
demanded by its worklist. Install declaration-only bindings in
projected environments and preserve empty projected imports as module
initialization dependencies.

Directly requested rootless modules stop after interface work unless a
declared library or diagnostic output requires a back pass. They do not
seed provider work; executable roots still drive exact selection.
Run reachability, row reconstruction, worklist closure, projection, and
witness-forwarding checks through one selective library test executable.

Compile and run end-to-end projects across deferred scheduling,
generated C, incremental invalidation, inheritance, native providers,
output locking, and consumer-specific provider output. Cover aliases,
optional truth conversion, inherited property layouts, module
initialization, declaration-only ABI types, and rootless module
requests.

The fixtures include the important cases carried over from dce2.
The deferred compiler now separates front-pass persistence, typed
reachability closure, selective materialization, and generation-bound
code generation. The old cache documentation described monolithic
interfaces and whole-module implementation hashes.

Describe exact interface rows and keys, module-owned hash components,
consumer-specific projections, constructor fragments, opaque and native
boundaries, snapshot validation, output locks, and the codegen hash.
Missing exact rows remain errors and never widen to wildcard interest.
Selective compilation computes both a closed project selection and
per-module dependency facts, but neither was available for inspection.

Let acton sig --reachability with no target print the project selection
without running back jobs or mixing the report with build progress.
Accept "." as an explicit project target.

Module and exact-name targets inspect cached TYDB facts. That inspection
may enumerate a requested module; normal selection continues to use
exact-key reads.

Render both views deterministically for human review and regression
testing.
The lock test assumed a child compiler reached the project lock within
500 ms. Compiler startup can take longer on macOS, letting the parent
release the lock before the child attempts acquisition.

Read the child's line-buffered output until it reports waiting for the
lock, then release it and require the build to succeed. This proves the
failed immediate acquisition without depending on startup timing.
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