Skip to content

[Bulk index][Zig] Gate ZLS approximation and add a compiler Sema exporter #79

Description

@samchon

Outcome

Deliver two explicitly different Zig providers:

  1. a fast analyzer-level ZLS bulk exporter with partial authority; and
  2. the final strict path, a versioned exporter added inside the Zig compiler at
    the Sema/Zcu/InternPool boundary and connected to Zig's incremental
    build/watch state.

The ZLS milestone improves speed and navigation but cannot close this issue.

Current master baseline

No strict Zig provider is registered. PR #147 investigated the compiler's
autodoc output and intentionally declined to register a containment-only
producer because it would displace the generic ZLS lane that can answer
references. There is no committed strict Zig timing cell.

This is not an unimplemented use of an existing Sema export. Zig PR
#19208 removed the old
compiler-produced ZIR-derived JSON and redesigned autodoc around source plus a
Wasm analyzer that reparses pre-semantic data. Current -femit-docs does not
publish compiler Sema facts.

Therefore the final route requires a real compiler change, not a wrapper around
autodoc.

Phase A: ZLS analyzer exporter

ZLS is consumable as a pinned Zig module and owns:

  • build-runner/module discovery;
  • DocumentStore source/dependency state;
  • scope/declaration and type-analysis helpers; and
  • cross-file reference machinery.

Build a small Zig executable or narrow ZLS command that opens one resident
workspace, awaits readiness, walks declarations/AST/VM state once and emits
changed Graph Snapshot Protocol shards. Do not call the external LSP once per
symbol.

This provider may claim only analyzer-proven facts. Literal @import, lexical
containment, source declarations, references and some resolved calls/accesses
are useful. Comptime-generated declarations, full generic instantiation,
target-dependent evaluation and compiler diagnostics remain partial or
unsupported. ZLS itself documents semantic/comptime limitations and is not
compiler authority.

Pin Zig and ZLS as a compatible pair and record both commits. A ZLS source
object/AST index is not a persistent identity; synthesize source identities from
module/file, semantic owner path, declaration kind/name and structural
signature, with explicit instability for anonymous/generated entities.

Phase B: compiler Sema exporter

Maintain an upstreamable narrow Zig compiler patch that:

  1. observes resolved declarations, types, functions and expressions at Sema;
  2. maps compiler interned identities back to source/module/build evidence;
  3. records direct dependency/invalidation keys from Zcu/InternPool;
  4. writes content-addressed declaration/source shards;
  5. emits diagnostics and unresolved comptime/generated sites; and
  6. participates in the incremental build-server/watch generation rather than
    launching a separate full compiler.

The exact internal hook names are version-sensitive. The protocol handshake
must state Zig commit, exporter schema and supported fact families; an unknown
compiler build declines rather than loading an ABI-compatible-looking patch.

Do not reconstruct typed facts from ZIR/autodoc. The redesign explicitly moved
autodoc away from unavailable semantic data, and pre-Sema source/ZIR cannot
prove resolved calls or comptime effects.

Facts and limits

The strict compiler path should cover:

  • declarations, containers, namespaces/modules, visibility and exports;
  • literal/resolved imports and build-module dependencies;
  • resolved calls, field accesses, construction/init expressions and type refs;
  • compile-time-generated declarations with origin/evaluation evidence;
  • tests and compiler diagnostics; and
  • references from compiler dependency/use data.

Zig has no class inheritance/interface/decorator model. Mark extends,
implements, overrides, decorates and renders unsupported instead of
fabricating analogies. Hand-rolled *anyopaque/function-pointer vtables do not
yield an exact runtime dispatch target; record dynamic candidates/unresolved
sites only when the compiler proves them.

Computed @import, reflection builtins, generated declarations and target/
comptime branches carry explicit dynamic, macro-or-generated or
conditional-build coverage.

Identity and universe

The universe includes Zig compiler/exporter commit, build graph/module,
target/CPU/features, optimization mode, build options, package dependencies,
global cache identity, build runner, compiler flags, generated inputs and
environment used by build.zig.

Persistent declarations use package/module coordinate, owner path, kind/name
and structural type/signature. Compiler interned IDs may be used only inside one
generation unless upstream guarantees cross-run stability. Exact fixtures
cover same-named declarations in scopes, anonymous structs, generic/comptime
specializations and generated declarations.

Incremental and performance behavior

Phase A keeps one ZLS DocumentStore; source/config changes use ZLS
invalidation and re-export affected files/modules.

Phase B connects to Zig's incremental compiler/build-server/watch state:

  • no-op: validated shard manifest, no semantic rerun;
  • body edit: compiler invalidates and re-exports the affected declaration/module
    closure;
  • public/comptime/build option change: trace dependent invalidation;
  • create/delete/rename: explicit shard update/removal; and
  • failed Sema, cancel or compiler crash: no partial commit.

Cold strict overhead is compared with the identical native Zig semantic build.
There must be no second compiler invocation for graph work.

Implementation map

  1. Add [Bulk index] Replace symbol-by-symbol LSP scans with compiler-owned snapshots #63's protocol/coverage contract.
  2. Implement/pin the ZLS analyzer sidecar and exact partial fixture.
  3. Publish its authority/coverage without registering it as compiler strictness.
  4. Prototype the compiler exporter against one pinned Zig revision; upstream the
    protocol/hook where possible.
  5. Connect shard invalidation to the incremental build/watch path.
  6. Register the compiler provider only after exact Sema facts, lifecycle and
    packaging pass.

Acceptance

  • Phase A uses ZLS in-process/workspace state and performs no per-symbol LSP
    fan-out.
  • Phase A and B have different provider names, authority and coverage.
  • The strict path resolves calls/types/comptime-generated declarations from
    Sema, not ZIR/autodoc guesses.
  • Exact fixtures cover modules/imports, structs/unions/enums, methods,
    generics, comptime, tests, target branches, build options and generated
    declarations.
  • All 15 fact families have explicit coverage/unresolved rows.
  • Compiler/ZLS pair, target and build universe are pinned and reported.
  • No-op, edit, API/comptime/config, create/delete/rename, error, cancel,
    crash and retry are atomic and incremental.
  • Cold overhead is measured against native Zig build; no-op/edit phases are
    separate.
  • Unsupported platforms/toolchains decline to ZLS/static truthfully.
  • Focused tests, Zig experiments, pnpm build, pnpm test, and
    pnpm coverage pass.

Primary references

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions